2019安徽省程序设计竞赛 I.你的名字(序列自动机)
这题和今年南昌邀请网络预选赛M题很像啊,不过主串数量不是一个了
都是在主串中判断子串是不是属于主串的一个子序列
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 1000 + 5; const int maxm = 30 + 5; char s1[maxn], s2[maxm]; int Next[maxn][maxn][26], last[26], ans[maxn]; int n, m; int main(){ // freopen("in.txt", "r", stdin); //输入文件里最后一行后要加回车,不然会死循环 scanf("%d%d", &n, &m); getchar(); memset( ans, 0, sizeof(ans) ); memset( Next, -1, sizeof(Next) ); for( int i=0; i<n; i++ ){ char ch, tot = 0; while( (ch=getchar())!='\n' ){ if( ch>='A' && ch<='Z' ) ch += 'a'-'A'; s1[++tot] = ch; } s1[++tot] = 0; memset( last, 0, sizeof(last) ); for( int j=1; j<tot; j++ ){ int id = s1[j]-'a'; for( int k=j-1; k>=last[id]; k-- ) Next[i][k][id] = j; //Next数组存第i个主串k位置后第一个id字符所在的位置 last[id] = j; } } for( int i=0; i<m; i++ ){ //输入进来每个模式串 char ch, tot=0; while( (ch=getchar())!='\n' ){ if( ch>='A' && ch<='Z' ) ch += 'a'-'A'; s2[tot++] = ch; } s2[tot] = 0; for( int j=0; j<n; j++ ){ //对每个主串进行匹配 int pos = 0; bool ok = 1; for( int k=0; k<tot; k++ ){ int id = s2[k]-'a'; if( Next[j][pos][id]!=-1 ) pos = Next[j][pos][id]; //如果成功继续匹配下一字符 else{ //匹配不成功,即该字符在pos后没有出现,则break ok = 0; break; } } if( ok ) ans[j] ++; //每个主串成功匹配一个模式串后价值数+1 } } for( int i=0; i<n; i++ ) printf("%d\n", ans[i]); //逐个输出 return 0; }