您的位置:首页 > 其它

[POJ2243]考研路茫茫——单词情结

2016-03-29 22:07 239 查看
  又是AC自动机上用矩乘优化DP= =

  其实和上一题基本一样。。。补集转化思想。。

  只是要多弄一个小矩阵求(26^1+26^2+....+26^L),并且也要求f的总和(因为是长度<=L)

  直接调上一题的伪板子了= =

  喜闻乐见CE了好几发。。。就因为iostream里有next这个名字的函数>_<(那我上一题怎么没CE啊摔

#include<cstdio>
#include<cstring>
#define ll long long
#define ull unsigned long long
using namespace std;
int dl[33],fail[33],num[33];
int ch[33][26],tot,next[33][26];
ull mp[36][36];
ull c[36][36],tmp[36][36],ans;
int i,j,k,n,m,l,r,cnt;
bool gg[103];
char s[23];

ll tm[103],t[103];

inline void trie(int n){
int i,p=0;
for(i=0;i<n;i++){
s[i]-='a';
if(!ch[p][s[i]])ch[p][s[i]]=++tot,p=tot;
else p=ch[p][s[i]];
}
gg[p]=1;//printf("gg:  %d\n",p);
}
inline void getfail(){
int l=0,r=1,i,j,now,p;dl[1]=0;
while(l<r){
now=dl[++l];//printf("   %d  fail:%d    gg:%d\n",now,fail[now],gg[now]);
for(i=0;i<26;i++)if(ch[now][i]){
j=ch[now][i];//printf("  %d-->%d\n",now,j);
for(p=fail[now];p&&!ch[p][i];p=fail[p]);
if(!now)fail[j]=0;else fail[j]=ch[p][i];
dl[++r]=j;gg[j]|=gg[fail[j]];
}
}
}
inline void getnext(){
l=0,r=1;int i,now,p;dl[1]=0;
while(l<r){
now=dl[++l];//printf("    %d\n",now);
for(i=0;i<26;i++){
if(ch[now][i]){
if(gg[ch[now][i]])next[now][i]=-1;
else next[now][i]=ch[now][i],dl[++r]=ch[now][i];
}
else{
for(p=fail[now];p&&!ch[p][i];p=fail[p]);
next[now][i]=gg[ch[p][i]]?-1:ch[p][i];
}
//            printf("%d %d  next:%d\n",now,i,next[now][i]);
}
}
}
inline void upd(){
cnt=0;int i,j;
for(i=1;i<=r;i++)
num[dl[i]]=++cnt;
for(i=1;i<=r;i++){
j=dl[i];
for(k=0;k<26;k++)if(next[j][k]!=-1)
mp[num[next[j][k]]][num[j]]++;
}

//    for(i=1;i<=r;puts(""),i++)
//        for(j=1;j<=r;j++)printf("   %lld",mp[i][j]);
}

inline void multoc(){
register int i,j,k;
for(i=1;i<=cnt;i++)
for(j=1;j<=cnt;j++)
for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*c[k][j];
for(i=1;i<=cnt;i++)memcpy(c[i],tmp[i],(cnt+1)<<3);
}
inline void multomp(){
register int i,j,k;
for(i=1;i<=cnt;i++)
for(j=1;j<=cnt;j++)
for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*mp[k][j];
for(i=1;i<=cnt;i++)memcpy(mp[i],tmp[i],(cnt+1)<<3);
}

int main(){
while(scanf("%d%d",&n,&m)!=EOF){
for(i=1;i<=n;i++)scanf("%s",s),trie(strlen(s));
getfail(),getnext(),upd();
cnt++;
for(i=1;i<=cnt;i++)mp[cnt][i]=1;
cnt++,mp[cnt][cnt]=26,cnt++,mp[cnt][cnt-1]=mp[cnt][cnt]=1;

//    for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf("  %llu",mp[i][j]);

for(i=1;i<=cnt;i++)c[i][i]=1;

/*        tm[1]=1;
for(i=1;i<=m;i++){
for(j=1;j<=cnt;j++)
for(k=1,t[j]=0;k<=cnt;k++)t[j]=(t[j]+mp[j][k]*tm[k])%modd;
memcpy(tm,t,sizeof(t));
}*/

while(m){
if(m&1)
multoc();
m>>=1;if(m)multomp();
//        for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf("  %llu",c[i][j]);
}

//        for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf("  %llu",c[i][j]);
//for(i=1,ans=0;i<=cnt;i++)ans=(ans+c[i][1])%modd;
ull ans=c[cnt][cnt-1]*26;
for(i=1;i<=cnt-2;i++)ans-=c[i][1];
printf("%I64u\n",ans+1);

memset(mp,0,sizeof(mp)),memset(c,0,sizeof(c)),
memset(ch,0,(tot+1)*4*26),memset(next,0,(tot+1)*4*26),memset(fail,0,(tot+1)<<2),memset(gg,0,tot+1),tot=0;
}
//    for(i=1,ans=0;i<=cnt;i++)ans=(ans+tm[i])%modd;
//    printf("%lld\n",ans);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: