hdu2222这题说的是在一个1000000的长串中找出n个短串是否在其中出现过 最后输出在长串中出现的个数
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <queue> #include <string> using namespace std; const int maxn =10000*50+100; const int sign_size = 26; map<string,int>ms; struct Acuth{ int ch[maxn][sign_size]; int val[maxn]; int sz; int f[maxn]; int last[maxn]; bool use[10005]; void clear(){ memset(ch[0],0,sizeof(ch[0])); memset(use,false,sizeof(use)); sz=1; ms.clear(); val[0]=0; } int idx(char c){ return c-'a'; } void insert(char *s,int v){ int n = strlen(s), u=0; for(int i=0; i<n; ++i){ int c=idx(s[i]); if(ch[u][c]==0){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } ms[string(s)]=v; val[u]=v; } void print(int j){ if(j){ use[val[j]] = true; print(last[j]); } } void find(char *T){ int n = strlen(T); int j=0; for(int i=0; i<n; ++i){ int c = idx(T[i]); while(j&&!ch[j][c]) j=f[j]; j=ch[j][c]; if(val[j]) print(j); else if(last[j]) print(last[j]); } } void getFail(){ queue<int> q; f[0]=0; for(int c = 0; c<sign_size; ++c){ int u = ch[0][c]; if(u){ f[u]=0; q.push(u); last[u]=0; } } while(!q.empty()){ int r= q.front(); q.pop(); for(int c=0; c<sign_size; ++c){ int u=ch[r][c]; if(!u){ ch[r][c] = ch[f[r]][c]; continue; } q.push(u); int v = f[r]; while(v&&!ch[v][c]) v=f[v]; f[u]=ch[v][c]; last[u] = val[f[u]]?f[u] : last[f[u]]; } } } }ac; char P[10005][55],text[1000005]; int main() { int t; scanf("%d",&t); while(t--){ ac.clear(); int n; scanf("%d",&n); for(int i=1; i<=n; ++i){ scanf("%s",P[i]); ac.insert(P[i],i); } scanf("%s",text); ac.getFail(); ac.find(text); int ans=0; for(int i=1; i<=n; ++i) if(ac.use[ms[string(P[i])]]==true) ans++; printf("%d ",ans); } return 0; }
uva11468 这题给出一些字符和各自对应的选择概率,随机选择L次后将得到一个长度为L 的随机字符串S。给出K个模板串,计算S不包含任何一个串的概率
利用自动机可以快速匹配多个串的特性进行处理,不断地添加在构造的字符串的末尾位置,如果添加构成一个字符串就不添加否则就添加
#include <iostream> #include <string.h> #include <cstdio> #include <queue> #include <vector> using namespace std; const int maxn = 20*20+10; const int sign_size = 1<<9; struct AUthac{ int ch[maxn][sign_size]; int val[maxn]; int sz; int f[maxn]; bool match[maxn]; void clear(){ memset(ch[0],0,sizeof(ch[0])); sz=1; memset(match,false,sizeof(match)); val[0]=0; } void insert(char *s,int v){ int n=strlen(s),u=0; for(int i=0; i<n; ++i){ int c = s[i]; if(ch[u][c]==0){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=v; match[u] = true; } void getFail(){ queue<int> q; f[0]=0; for(int c=0; c<sign_size; c++){ int u = ch[0][c]; if(u){ q.push(u); f[u]=0; } } while(!q.empty()){ int r = q.front(); q.pop(); for(int c= 0; c<sign_size; ++c){ int u = ch[r][c]; if(u==0){ ch[r][c]=ch[f[r]][c];continue; } q.push(u); int v = f[r]; while( v && !ch[v][c] ) v = f[v] ; f[u]=ch[v][c]; match[u] |= match[f[u]]; } } } }ac; double pro[sign_size]; char str[sign_size]; int L,n,K; bool vis[maxn][105]; double dp[maxn][105]; vector<char> P; double dfs(int loc,int leave){ if(leave==0) return 1; if(vis[loc][leave]==true) return dp[loc][leave]; double ans=0; for(int i=0; i<n; ++i){ int c = P[i]; if(ac.match[ac.ch[loc][c]]==false) ans+= pro[i] * dfs( ac.ch[loc][c], leave - 1 ); } vis[loc][leave] = true; dp[loc][leave] = ans; return ans; } int main() { int t,cas=0; char S[30]; scanf("%d",&t); while(t--){ ac.clear(); scanf("%d",&K); for(int i=1; i<=K; ++i){ scanf("%s",S); ac.insert(S,i); } ac.getFail(); scanf("%d",&n); P.clear(); for(int i =0; i<n; i++){ scanf("%s",str); P.push_back(str[0]); scanf("%lf",&pro[i]); } memset(vis,false,sizeof(vis)); scanf("%d",&L); double ans=dfs(0,L); printf("Case #%d: %.6lf ",++cas,ans); } return 0; }
uva11019
题意 给出一个n*m的字符矩阵T,你的任务是找出给定的x*y的字符矩阵P出现了多少次。 即需要在二维文本串T中查找二维模式串P。
因为是以矩阵P为模板然后将P的每行都挂在自动机上接下来,如果存在相同的串就讲该串与上一个相同的串用一个next数组存下关系,接下来将文本矩阵T每行都去与自动机匹配每当匹配到一行是 这个行所在的那个矩阵可匹配个数加1(cnt[r][c]表示以r行c列为左上角的矩阵)
做完所有的行后 统计每个位置为起始点的可匹配数如果等于x那么这就是一个可匹配的矩阵。
#include <iostream> #include <cstdio> #include <string.h> #include <queue> using namespace std; const int maxn = 100*100+100; const int sign_size = 26; int cnt[1001][1001],len[105]; struct Acuthmechion{ int ch[maxn][sign_size]; int val[maxn]; int sz; int next[maxn]; int f[maxn],last[maxn]; int idx(char c){ return c-'a'; } void clear(){ sz=1; val[0]=0; memset(ch[0],0,sizeof(ch[0])); memset(cnt,0,sizeof(cnt)); } void insert(char *s,int v){ int n=strlen(s),u=0; len[v]=n; for(int i=0; i<n; ++i ){ int c = idx(s[i]); if(ch[u][c]==0){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } next[v]=val[u]; val[u]=v; } void print(int row,int colun, int j){ if(val[j]){ for(int i = val[j]; i!=0; i=next[i]){ int t1 = row-(i-1); int t2 = colun-(len[i]-1); if(t1>=0&&t2>=0) ++cnt[t1][t2]; } print(row,colun,last[j]); } } void find(char *T,int row){ int n=strlen(T); int j=0; for(int i=0; i<n; ++i){ int c = idx(T[i]); while(j&&ch[j][c]==0) j=f[j]; j=ch[j][c]; if(val[j]) print(row,i,j); else if(last[j]) print(row,i,last[j]); } } void geiFail(){ queue<int> q; last[0]=f[0]=0; for(int c=0; c<sign_size; ++c){ int u=ch[0][c]; if(u){ f[u]=0; q.push(u); last[u]=0;} } while(!q.empty()){ int r = q.front(); q.pop(); for(int c=0; c<sign_size; ++c){ int u = ch[r][c]; if(u==0){ ch[r][c]=ch[f[r]][c]; continue; } q.push(u); int v=f[r]; while(v&&ch[v][c]==0) v=f[v]; f[u]=ch[v][c]; last[u]=val[f[u]] ? f[u]:last[f[u]]; } } } }ac; char xy[105][105]; char nm[1005][1005]; int main() { int cas,n,m,x,y; scanf("%d",&cas); while(cas--){ ac.clear(); scanf("%d%d",&n,&m); for(int i=0; i<n; ++i) scanf("%s",nm[i]); scanf("%d%d",&x,&y); for(int i=0; i<x; ++i){ scanf("%s",xy[i]); ac.insert(xy[i],i+1); } ac.geiFail(); for(int i=0; i<n; ++i){ ac.find(nm[i],i); } int ans=0; for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) if(cnt[i][j]==x) ans++; printf("%d ",ans); } return 0; }
的