POJ1625 Censored!(AC自动机+DP)
题目问长度m不包含一些不文明单词的字符串有多少个。
依然是水水的AC自动机+DP。。做完后发现居然和POJ2778是一道题,回过头来看都水水的。。。
- dp[i][j]表示长度i(在自动机转移i步)且后缀状态为自动机第j个结点的合法字符串数
- dp[0][0]=1
- 转移转移。。。
注意要用高精度,因为答案最多5050。
还有就是要用unsigned char,题目的输入居然有拓展的ASCII码,编码128-255。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 int tn,ch[555][256],fail[555],flag[555]; 7 void insert(unsigned char *s){ 8 int x=0; 9 for(int i=0; s[i]; ++i){ 10 int y=s[i]; 11 if(ch[x][y]==0) ch[x][y]=++tn; 12 x=ch[x][y]; 13 } 14 flag[x]=1; 15 } 16 void init(){ 17 memset(fail,0,sizeof(fail)); 18 queue<int> que; 19 for(int i=0; i<256; ++i){ 20 if(ch[0][i]) que.push(ch[0][i]); 21 } 22 while(!que.empty()){ 23 int x=que.front(); que.pop(); 24 for(int i=0; i<256; ++i){ 25 if(ch[x][i]) que.push(ch[x][i]),fail[ch[x][i]]=ch[fail[x]][i],flag[ch[x][i]]|=flag[ch[fail[x]][i]]; 26 else ch[x][i]=ch[fail[x]][i]; 27 } 28 } 29 } 30 #define ULL unsigned long long 31 #define M 1000000000000000000L 32 struct BigInt{ 33 ULL bit[5]; 34 BigInt(int a=0){ 35 bit[0]=bit[1]=bit[2]=bit[3]=0; 36 bit[4]=a; 37 } 38 }; 39 BigInt operator+(const BigInt &b1,const BigInt &b2){ 40 BigInt b; 41 ULL carry=0; 42 for(int i=4; i>=0; --i){ 43 ULL tmp=b1.bit[i]+b2.bit[i]+carry; 44 b.bit[i]=tmp%M; 45 carry=tmp/M; 46 } 47 return b; 48 }; 49 void output(const BigInt &b){ 50 int i=0; 51 while(i<5 && b.bit[i]==0) ++i; 52 if(i==5){ 53 puts("0"); 54 return; 55 } 56 printf("%llu",b.bit[i]); 57 for(int j=i+1; j<5; ++j){ 58 printf("%018llu",b.bit[j]); 59 } 60 putchar('\n'); 61 } 62 int main(){ 63 BigInt one(1); 64 unsigned char str[55]; 65 int n,m,p; 66 while(~scanf("%d%d%d",&n,&m,&p)){ 67 scanf("%s",str); 68 bool vis[256]={0}; 69 for(int i=0; str[i]; ++i) vis[str[i]]=1; 70 tn=0; 71 memset(ch,0,sizeof(ch)); 72 memset(flag,0,sizeof(flag)); 73 for(int i=0; i<p; ++i){ 74 scanf("%s",str); 75 insert(str); 76 } 77 init(); 78 BigInt **d=new BigInt*[m+1]; 79 for(int i=0; i<=m; ++i) d[i]=new BigInt[tn+1]; 80 d[0][0]=one; 81 for(int i=0; i<m; ++i){ 82 for(int j=0; j<=tn; ++j){ 83 if(flag[j]) continue; 84 for(int k=33; k<256; ++k){ 85 if(!vis[k] || flag[ch[j][k]]) continue; 86 d[i+1][ch[j][k]]=d[i+1][ch[j][k]]+d[i][j]; 87 } 88 } 89 } 90 BigInt res=0; 91 for(int i=0; i<=tn; ++i) res=res+d[m][i]; 92 output(res); 93 for(int i=0; i<=m; ++i) delete[] d[i]; 94 delete[] d; 95 } 96 return 0; 97 }