이 문제에 대한 해결책 P2292 [HNOI2004] L 언어]

주제 링크

용액 [HNOI2004] L 언어

항목 효과 : 소정 (n \) \가 사전의 단어와 \ (m의 \) 문서의 섹션 문서 각 부분이 사전에 알 수있는 최장 프리픽스 요청

분석 :이 질문은 주로 어렵다 \ (DP \) 최적화

우리는 \ (F [I] \) 표현 전에 \ (나는 \) 문자열 이해하면 외관상 :

$의 F [I]는 = F의 [I] ||; F [J-1] \ 쿼드 j 개의 \ 당량의 I와; STR [J, I] \ 낱말 $

\ (ANS = 최대 \ {내가 \ 미드 F [I] = 1 \} \)

\ (STR \) 테이블 원래 문자열은 \ (단어 \) 사전 (곤약 정말이 표현하는 방법을 몰라 ) \ (DP \를 QAQ을 방정식)

명백한 방정식, 우리가 어떻게 키 \ (DP \)

이 문제 \ (n \)은 각각의 워드 길이보다 더 매우 작은 \ (10 \) 은 더 이상보다 각각 에세이 \ (1M \) , 즉 \ (10 ^ 6 \)

심한 경우 \ (O (N ^ 2) DP의 \) 각각의 키 워드 길이를 초과하지 않는 것을 특징 복잡성 직접 하늘, \ (10 \)를 우리가 열거 정의 할 수 있도록, \를 (J \) 범위

사전에 어떻게 하위 문자열을 판단하는 방법 아닌가요?

  • \(해시시\)
  • \ (STL의 \) 대법 포효 아 (unordered_set)

살 수 느낌, 내가 작성하지 않은

우리가 열거하기 때문에 \ (J의 \)를 순서는 무관하다, 그래서 우리는 뒤로 열거 할 수 있습니다 \ (J의 \)

단어는 다음 거꾸로 삽입 \ (트리는 \) 트리를 다음 할 \ (DP \) 열거 \ (J \)(트리는 \) \의 트리를 걸어 \ (트리는 \) 트리 노드가 표시된 후 시간 \ (STR [J, I] \ 낱말 \)

그것은 코드, 매우 추상적 인 즉 :

#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1e6 + 100;
char str[maxn];
namespace Trie{
    const int maxnode = 512,sigmasize = 26;
    int ch[maxnode][sigmasize],val[maxnode],tot;
    inline int idx(char c){return c - 'a';}
    inline void insert(){
        int len = strlen(str + 1),u = 0;
        for(int i = len;i >= 1;i--){//倒着插入
            int c = idx(str[i]);
            if(!ch[u][c])ch[u][c] = ++tot;
            u = ch[u][c];
        }
        val[u] = 1;
    }
    bool f[maxn];
    inline void query(){
        int len = strlen(str + 1),ans = 0;
        memset(f,0,sizeof(f));f[0] = 1;//初始化
        for(int i = 1;i <= len;i++){
            int u = 0;
            for(int j = i;j >= 1;j--){//倒着枚举j
                int c = idx(str[j]);
                if(!ch[u][c])break;//走不动了后面也不可能有单词了
                u = ch[u][c];
                if(val[u])f[i] |= f[j - 1];//str[j,i]在字典里
            }
            if(f[i])ans = i;//刷新ans
        }
        printf("%d\n",ans);
    }
}
int n,m;
int main(){
#ifdef LOCAL
    freopen("fafa.in","r",stdin);
#endif
    scanf("%d %d",&n,&m);
    for(int i = 1;i <= n;i++)
        scanf("%s",str + 1),Trie::insert();
    for(int i = 1;i <= m;i++)
        scanf("%s",str + 1),Trie::query();
    return 0;
}

추천

출처www.cnblogs.com/colazcy/p/11515094.html