#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 30 #define MAXN 2000005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define mid int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define meminf(x) memset(x,INF,sizeof(x)) #define lowbit(x) (x&-x) const LL mod = 1000000; const int prime = 999983; const int INF = 0x3f3f3f3f; const int INFF = 1e9; const double pi = 3.141592653589793; const double inf = 1e18; const double eps = 1e-10; /**************读入外挂*********************/ inline int read_int(){ int ret=0; char tmp; while(!isdigit(tmp=getchar())); do{ ret=(ret<<3)+(ret<<1)+tmp-'0'; } while(isdigit(tmp=getchar())); return ret; } /*******************************************/ struct node{ bool isword; int next[15]; void init(){ memset(next,0,sizeof(next)); isword=false; } } tree[100010]; char s[15]; bool ok; int num; void insert(char a[]){ int cou=0; int index=0; int len=strlen(a); for(int i=0; i<len; i++){ if(tree[index].next[a[i]-'0']==0){ tree[++num].init();//建立新节点 tree[index].next[a[i]-'0']=num;//连接 index=num; } else{ cou++; index=tree[index].next[a[i]-'0']; if(tree[index].isword){ ok=false; return; } } } tree[index].isword=true; if(cou==len) ok=false; } int main(){ int kase=1; ok=true; num=0; while(cin>>s){ if(s[0]=='9'){ if(!ok) printf("Set %d is not immediately decodable\n",kase); else printf("Set %d is immediately decodable\n",kase); kase++; ok=true; num=0; mem0(tree); } insert(s); } return 0; }
int a[MAX]; int b[10005]; int f[10005]; int n,m; void getFail(){ f[0]=0; f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j&&b[i]!=b[j]) j=f[j]; f[i+1]=(b[i]==b[j])?j+1:0; } } void solve(){ getFail(); int j=0; int flag=0; for(int i=0;i<n;i++){ while(j&&b[j]!=a[i]) j=f[j]; if(b[j]==a[i]) j++; if(j==m){ printf("%d\n",i-m+2);//就这个匹配开始的端点要注意下 flag=1; break; } } if(!flag) printf("-1\n"); } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<m;i++) scanf("%d",&b[i]); solve(); } return 0; }
char a[MAX]; char b[10005]; int f[10005]; int n,m; void getFail(){ f[0]=0; f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j&&b[i]!=b[j]) j=f[j]; f[i+1]=(b[i]==b[j])?j+1:0; } } void solve(){ getFail(); int j=0; int num=0; for(int i=0;i<n;i++){ while(j&&b[j]!=a[i]) j=f[j]; if(b[j]==a[i]) j++; if(j==m){ num++; } } printf("%d\n",num); } int main(){ int t; scanf("%d",&t); while(t--){ mem0(f); scanf("%s%s",b,a); n=strlen(a); m=strlen(b); solve(); } return 0; }
char a[MAX]; char b[100005]; int f[100005]; int n,m; void getFail(){ f[0]=0; f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j&&b[i]!=b[j]) j=f[j]; f[i+1]=(b[i]==b[j])?j+1:0; } } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%s",b); m=strlen(b); getFail(); if(f[m]==0) printf("%d\n",m); else{ int t=m-f[m]; if(m%t==0) printf("0\n"); else printf("%d\n",t-m%t); } } return 0; }
char a[MAX]; char b[MAX]; int f[MAX]; int n,m; void getFail(){ f[0]=0; f[1]=0; for(int i=1;i<n;i++){ int j=f[i]; while(j&&b[i]!=b[j]) j=f[j]; f[i+1]=(b[i]==b[j])?j+1:0; } } int main(){ int kase=0; while(scanf("%d",&n)&&n){ kase++; printf("Test case #%d\n",kase); scanf("%s",b); getFail(); for(int i=2;i<=n;i++){ if(f[i]==0) continue; int t=i-f[i]; if(i%t==0) printf("%d %d\n",i,i/t); } printf("\n"); } return 0; }
char a[MAX]; char b[MAX]; int f[MAX]; int n,m; void getFail(){ f[0]=0; f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j&&b[i]!=b[j]) j=f[j]; f[i+1]=(b[i]==b[j])?j+1:0; } } int main(){ while(scanf("%s",&b)){ if(b[0]=='.') break; //getchar(); m=strlen(b); getFail(); //printf("%d ",f[m]); if(f[m]>0&&m%(m-f[m])==0) printf("%d\n",m/(m-f[m])); else printf("1\n"); } return 0; }
char a[MAX]; char b[MAX]; int f[MAX]; int ans[MAX]; int n,m; void getFail(){ f[0]=0; f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j&&b[i]!=b[j]) j=f[j]; f[i+1]=(b[i]==b[j])?j+1:0; } } int main(){ while(~scanf("%s",b)){ m=strlen(b); getFail(); int tot=0; ans[tot++]=m; int k=m; while(f[k]){ ans[tot++]=f[k]; //printf("%d %d\n",k,f[k]); k=f[k]; } sort(ans,ans+tot); for(int i=0;i<tot;i++){ if(i!=tot-1) printf("%d ",ans[i]); else printf("%d\n",ans[i]); } } return 0; }
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 1000005 #define MAXN 2000005 #define maxnode 500010 #define sigma_size 30 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define mid int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define meminf(x) memset(x,INF,sizeof(x)) #define lowbit(x) (x&-x) const LL mod = 1000000; const int prime = 999983; const int INF = 0x3f3f3f3f; const int INFF = 1e9; const double pi = 3.141592653589793; const double inf = 1e18; const double eps = 1e-10; /**************读入外挂*********************/ inline int read_int(){ int ret=0; char tmp; while(!isdigit(tmp=getchar())); do{ ret=(ret<<3)+(ret<<1)+tmp-'0'; } while(isdigit(tmp=getchar())); return ret; } /*******************************************/ struct AC{ int ch[maxnode][sigma_size]; int val[maxnode], last[maxnode], f[maxnode]; //int cnt[maxnode]; //cnt是该模块出现过多少次。。该题目取最大的输出 int cnt; int sz; void init(){ mem0(ch[0]); //mem0(cnt); last[0]=val[0]=0; sz = 1; cnt=0; } int idx(char c){return c-'a';} void insert(const 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]){ mem0(ch[sz]); val[sz]=0; ch[u][c]=sz++; } u = ch[u][c]; } val[u]+=v;//考虑单词重复出现 } void bfs(){ queue<int>q; f[0]=0; for(int c = 0; c<sigma_size;c++){ int u = ch[0][c]; if(u){q.push(u); f[u]=last[u]=0;} } while(!q.empty()){ int r =q.front(); q.pop(); for(int c = 0;c<sigma_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]]; } } } void find(char *T){ int n = strlen(T); int u = 0; for(int i=0;i<n;i++){ int c = idx(T[i]); //while(u && !ch[u][c]) u = f[u]; u = ch[u][c]; if(val[u]) print(u); else if(last[u]) print(last[u]); } } void print(int j){ if(j){ cnt+=val[j]; val[j]=0; print(last[j]); } } }ac; char a[MAX]; int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); ac.init(); char s[55]; for(int i=0;i<n;i++){ scanf("%s",s); ac.insert(s,1); } ac.bfs(); scanf("%s",a); ac.find(a); printf("%d\n",ac.cnt); } return 0; }
void print(int j){ if(j){ vis[val[j]]=1; flag=1; print(last[j]); } }
void print(int j){ if(j){ cnt[val[j]]++; print(last[j]); } }
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 100005 #define MAXN 2000005 #define maxnode 110 #define sigma_size 4 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define mid int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define meminf(x) memset(x,INF,sizeof(x)) #define lowbit(x) (x&-x) const int prime = 999983; const int INF = 0x3f3f3f3f; const int INFF = 1e9; const double pi = 3.141592653589793; const double inf = 1e18; const double eps = 1e-10; const int mod = 100000; /**************¶ÁÈëÍâ¹Ò*********************/ inline int read_int(){ int ret=0; char tmp; while(!isdigit(tmp=getchar())); do{ ret=(ret<<3)+(ret<<1)+tmp-'0'; } while(isdigit(tmp=getchar())); return ret; } /*******************************************/ struct AC{ int ch[maxnode][sigma_size]; int val[maxnode], last[maxnode], f[maxnode]; int sz; void init(){ mem0(ch[0]); last[0]=val[0]=0; sz = 1; } int idx(char c){ switch(c){ case 'A': return 0; case 'T': return 1; case 'C': return 2; case 'G': return 3; default: return -1; } } void insert(const char *s,int v){ int n = strlen(s), u =0; for(int i=0;i<n;i++){ int c = idx(s[i]); if(c==-1) return ; if(!ch[u][c]){ mem0(ch[sz]); val[sz]=0; ch[u][c]=sz++; } u = ch[u][c]; } val[u]=v; } void bfs(){ queue<int>q; f[0]=0; for(int c = 0; c<sigma_size;c++){ int u = ch[0][c]; if(u){q.push(u); f[u]=last[u]=0;} } while(!q.empty()){ int r =q.front(); q.pop(); for(int c = 0;c<sigma_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; struct Matrix{ int n; LL maze[maxnode][maxnode]; void init(int n){ this->n = n; mem0(maze); } Matrix operator * (Matrix &rhs){ Matrix m; m.init(n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) m.maze[i][j] = (m.maze[i][j] + maze[i][k] * rhs.maze[k][j])%mod; return m; } }; int qpow(Matrix a,int n){ Matrix ans; ans.init(a.n); for(int i=0;i<ans.n;i++) ans.maze[i][i] = 1; while(n){ if(n&1) ans = ans * a; a = a*a; n >>= 1; } int sum = 0; for(int i=0;i<ans.n;i++) sum = (sum + ans.maze[0][i]) % mod; return sum; } char s[20]; int main(){ int n,m; scanf("%d%d",&n,&m); ac.init(); for(int i=0;i<n;i++){ scanf("%s",s); ac.insert(s,1); } ac.bfs(); Matrix A; A.init(ac.sz); for(int i=0;i<ac.sz;i++){ for(int j=0;j<sigma_size;j++){ int v=ac.ch[i][j]; if(ac.val[v]) continue; else if(ac.last[v]) continue; A.maze[i][v]++; } } printf("%d\n",qpow(A,m)); return 0; }
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 5005 #define MAXN 1000005 #define maxnode 1005 #define sigma_size 4 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define mid int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) const int prime = 999983; const int INF = 0x3f3f3f3f; const int INFF = 1e9; const double pi = 3.141592653589793; const double inf = 1e18; const double eps = 1e-10; const LL mod = (1<<64); /**************¶ÁÈëÍâ¹Ò*********************/ inline int read_int(){ int ret=0; char tmp; while(!isdigit(tmp=getchar())); do{ ret=(ret<<3)+(ret<<1)+tmp-'0'; } while(isdigit(tmp=getchar())); return ret; } /*******************************************/ struct AC{ int ch[maxnode][sigma_size]; int val[maxnode], last[maxnode], f[maxnode]; //int cnt[maxnode]; //cnt是该模块出现过多少次。。该题目取最大的输出 int cnt; int sz; void init(){ mem(ch[0],0); //mem0(cnt); last[0]=val[0]=0; sz = 1; cnt=0; } int idx(char c){ switch(c){ case 'A':return 0; case 'T':return 1; case 'C':return 2; case 'G':return 3; } } void insert(const 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]){ mem(ch[sz],0); val[sz]=0; ch[u][c]=sz++; } u = ch[u][c]; } val[u]=v;//考虑单词重复出现 } void bfs(){ queue<int>q; f[0]=0; for(int c = 0; c<sigma_size;c++){ int u = ch[0][c]; if(u){q.push(u); f[u]=last[u]=0;} } while(!q.empty()){ int r =q.front(); q.pop(); for(int c = 0;c<sigma_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]]; } } } void find(char *T){ int n = strlen(T); int u = 0; for(int i=0;i<n;i++){ int c = idx(T[i]); //while(u && !ch[u][c]) u = f[u]; u = ch[u][c]; if(val[u]) print(u); else if(last[u]) print(last[u]); } } void print(int j){ if(j){ print(last[j]); } } }ac; char s[MAX]; int dp[1005][1005]; int main(){ int n,kase=0; while(scanf("%d",&n)&&n){ ac.init(); for(int i=0;i<n;i++){ scanf("%s",s); ac.insert(s,1); } ac.bfs(); scanf("%s",s); int len=strlen(s); mem(dp,INF); dp[0][0]=0; for(int i=1;i<=len;i++){ for(int j=0;j<ac.sz;j++){ if(dp[i-1][j]==INF) continue; for(int k=0;k<4;k++){ int p=ac.ch[j][k]; //j状态下k转移去的节点 if(ac.val[p]==0&&ac.last[p]==0){ dp[i][p]=min(dp[i][p],dp[i-1][j]+(ac.idx(s[i-1])!=k)); } } } } int mini=INF; for(int i=0;i<ac.sz;i++){ mini=min(mini,dp[len][i]); } kase++; printf("Case %d: ",kase); if(mini==INF) printf("-1\n"); else printf("%d\n",mini); } return 0; }
hdu 2243
题意:给你n个字符串,问你长度小于等于m的字符串中必须出现这n个其中一个子串的字符串有多少情况
题解:前面做过一定不能出现,现在是反过来考虑,所以先考虑所有字符串,就是从26^1+26^2+......+26^m,这个用快速幂+递归求等比数列就好了
然后是计算长度小于等于m的字符串中不能出现上述字符串的个数,两个相减就是结果
由于是模1<<64,直接用unsigned long long即可,会自动模
难点就在于这个n个字符串组成的矩阵
首先是构造AC自动机,然后如果val[j],last[j]不为0的话就continue,为0的地方就在矩阵上++(可以到达)
然后就是求A^1+A^2+……+A^m这个矩阵的第一行的和
如果用快速幂+递归很有可能爆掉
矩阵是一种十分奇妙的东西,假如矩阵A是n行n列,年神教我开成n+1行n+1列,最后一行都是0,最后一列都是1(A[n+1][n+1]=1)
这样的话两个矩阵相乘,第一行的前n个,还是和n*n的两个A相乘一样,第一行的最后一个值,就是n+1个1和另外个A的第一行相乘,值是A的第一行的值+1
以此类推,第二次得到的最后一个值就是A^2+A的第一行的值+1,最后得到的就是A^m-1+……+1,然后只要把最后得到的矩阵的第一行相加即可
如此巧妙的技巧我必须以后多加练习,矩阵的优化是十分的奇妙
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 100005 #define MAXN 2000005 #define maxnode 110 #define sigma_size 26 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define mid int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define meminf(x) memset(x,INF,sizeof(x)) #define lowbit(x) (x&-x) const int prime = 999983; const int INF = 0x3f3f3f3f; const int INFF = 1e9; const double pi = 3.141592653589793; const double inf = 1e18; const double eps = 1e-10; const LL mod = (1<<64); /**************¶áèëía1ò*********************/ inline int read_int(){ int ret=0; char tmp; while(!isdigit(tmp=getchar())); do{ ret=(ret<<3)+(ret<<1)+tmp-'0'; } while(isdigit(tmp=getchar())); return ret; } /*******************************************/ struct AC{ int ch[maxnode][sigma_size]; int val[maxnode], last[maxnode], f[maxnode]; int sz; void init(){ mem0(ch[0]); last[0]=val[0]=0; sz = 1; } int idx(char c){return c-'a';} void insert(const char *s,int v){ int n = strlen(s), u =0; for(int i=0;i<n;i++){ int c = idx(s[i]); if(c==-1) return ; if(!ch[u][c]){ mem0(ch[sz]); val[sz]=0; ch[u][c]=sz++; } u = ch[u][c]; } val[u]=v; } void bfs(){ queue<int>q; f[0]=0; for(int c = 0; c<sigma_size;c++){ int u = ch[0][c]; if(u){q.push(u); f[u]=last[u]=0;} } while(!q.empty()){ int r =q.front(); q.pop(); for(int c = 0;c<sigma_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; struct Matrix{ int n; ull maze[maxnode][maxnode]; void init(int n){ this->n = n; mem0(maze); } Matrix operator * (Matrix &rhs){ Matrix m; m.init(n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) m.maze[i][j] = m.maze[i][j] + maze[i][k] * rhs.maze[k][j]; return m; } Matrix operator + (Matrix &rhs){ Matrix m; m.init(n); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ m.maze[i][j] = maze[i][j] + rhs.maze[i][j]; } } return m; } }; ull qpow(Matrix a,int n){ Matrix ans; ans.init(a.n); for(int i=0;i<ans.n;i++) ans.maze[i][i] = 1; while(n){ if(n&1) ans = ans * a; a = a * a; n >>= 1; } ull tmp=0; for(int i=0;i<ans.n;i++) tmp+=ans.maze[0][i]; return tmp; } ull ppow(ull a,int m){ ull ans=1; ull b=a; while(m){ if(m&1) ans*=b; b*=b; m>>=1; } return ans; } char s[20]; int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ ac.init(); for(int i=0;i<n;i++){ scanf("%s",s); ac.insert(s,1); } ac.bfs(); Matrix A; A.init(ac.sz+1); for(int i=0;i<ac.sz;i++){ for(int j=0;j<sigma_size;j++){ int v=ac.ch[i][j]; if(ac.val[v]) continue; else if(ac.last[v]) continue; A.maze[i][v]++; } } for(int i=0;i<=ac.sz;i++) A.maze[i][ac.sz]=1; Matrix B; B.init(2); B.maze[0][0]=26;B.maze[0][1]=1; B.maze[1][0]=0; B.maze[1][1]=1; ull ans=qpow(B,m); ull tmp=qpow(A,m); cout<<ans-tmp<<endl; } return 0; }