链接 http://acm.fzu.edu.cn/problem.php?pid=2128
解题方法 首先考虑暴力,,就是拿每一个字符串在匹配串里面找到所有位置,然后从头到尾不断更新最长的合理位置pos 同时记录出 最长的长度; 想到这样会超时,所以 AC 自动机一下,找到任意一个后缀最长能匹配的位置 方法是: 在构建自动机的 fail 指针的时候,找到任意位置的任意字符最长公共前缀的时候看那个位置是否有单词存在;
#include<iostream> #include<stdio.h> #include<cstring> #include<algorithm> #include<cmath> using namespace std; struct date{ date *next[26],*fail; int len; bool flag; }tree[100005],*que[100005],*root; int N,total,tail,hed; char str[1000006],cha[102]; date *creat( ) { for( int i = 0; i < 26; i++ ) tree[total].next[i] = NULL; tree[total].fail = NULL; tree[total].flag = false; tree[total].len = 1000000; return &tree[total++]; } void inint( ) { total = hed = tail = 0; root = creat(); root->fail = root; } void insert( char *word,int len ) { date *temp = root; while( *word ) { int num = *word - 'a'; if( temp->next[num] == NULL ) temp->next[num] = creat(); temp = temp->next[num]; word++; } temp->len = len-1; temp->flag = true; } void build( ) { que[tail++] = root; while( tail > hed ) { date *temp = que[hed++]; for( int i = 0; i < 26; i++ ) if( temp->next[i] != NULL ){ if( temp == root )temp->next[i]->fail = root; else temp->next[i]->fail = temp->fail->next[i]; if( temp->fail->next[i]->flag ) temp->next[i]->len = min( temp->next[i]->len,temp->fail->next[i]->len ); que[tail++] = temp->next[i]; } else { if( temp == root )temp->next[i] = root; else temp->next[i] = temp->fail->next[i]; } } } short int res[1000006]; inline int max( int a,int b){return a>b?a:b;} inline int min( int a,int b){return a>b?b:a;} void search( char *word ) { int t = 0; date *temp = root; int len = strlen(word); while( *word ) { int num = *word - 'a'; temp = temp->next[num]; res[t] = temp->len; word++; t++; } int pre = 0; int Max = 0; for( int i = 0; i < len; i++ ){ pre = min( pre + 1,res[i] ); Max = max( Max,pre ); } printf("%d ",Max); } int main( ) { while( scanf("%s",&str) != EOF ) { scanf("%d",&N); inint( ); for( int i = 1; i <= N; i++ ){ scanf("%s",&cha); insert(cha,strlen(cha)); } build( ); search( str ); } return 0; }