용액 [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;
}