您的位置:首页 > 其它

AC自动机+DP(POJ2778&&POJ3691)

2016-03-22 08:27 316 查看
闲来无事AC自动机+DP撸两发QAQ

都是傻X题放代码就好了QAQ

POJ2778:AC自动机构建转移矩阵,矩阵快速幂优化dp

#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=10010;
const int mod=100000;
int n,m;
char str[2100];

struct AC_automation{
int next[maxn][4];
int end[maxn],fail[maxn];
int l,root;
LL a[101][101],b[101][101];
int newnode(){
for (int i=0;i<26;++i) next[l][i]=-1;
end[l]=fail[l]=0; return l++;
}
void init(){
l=0; root=newnode();
}
int idx(char c){
if (c=='A') return 0;
else if (c=='C') return 1;
else if (c=='G') return 2;
else return 3;
}
void ins(char buf[]){
int now=root,l=strlen(buf);
for (int i=0;i<l;++i){
int x=idx(buf[i]);
if (next[now][x]==-1)
next[now][x]=newnode();
now=next[now][x];
}end[now]=1;
}
void build(){
queue<int>q; fail[root]=root;
for (int i=0;i<4;++i)
if (next[root][i]!=-1){
q.push(next[root][i]);
fail[next[root][i]]=root;
}else next[root][i]=root;
while (!q.empty()){
int now=q.front(); q.pop();
for (int i=0;i<4;++i)
if (next[now][i]!=-1){
q.push(next[now][i]);
fail[next[now][i]]=next[fail[now]][i];
if (end[fail[next[now][i]]]) end[next[now][i]]=1;
}else next[now][i]=next[fail[now]][i];
}
}
void Init_Matrix(){
for(int i=0;i<l;++i)
for (int j=0;j<l;++j)
a[i][j]=b[i][j]=0;
for (int i=0;i<l;++i)
for (int j=0;j<4;++j)
if (!end[next[i][j]]&&!end[i])
a[i][next[i][j]]++;
b[0][0]=1;
}
void mul(LL a[101][101],LL b[101][101],LL c[101][101]){
LL tmp[101][101];
for (int i=0;i<l;++i)
for (int j=0;j<l;++j){
tmp[i][j]=0;
for (int k=0;k<l;++k)
tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
}
for (int i=0;i<l;++i)
for (int j=0;j<l;++j)
c[i][j]=tmp[i][j];
}
void Matrix_power(){
while (n){
if (n&1) mul(b,a,b);
mul(a,a,a); n>>=1;
}
LL ans=0;
for (int i=0;i<l;++i)
ans=(ans+b[0][i])%mod;
printf("%lld",ans);
}
}Ac;

int main(){
Ac.init();
scanf("%d%d",&m,&n);
for (int i=1;i<=m;++i){
scanf("%s",str);
Ac.ins(str);
}
Ac.build();
Ac.Init_Matrix();
Ac.Matrix_power();
}


POJ3691:dp[i][j]表示匹配到长度为i且正在j节点的最少修改次数
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1010;
const int mod=100000;
int n,m;
char str[2100];

struct AC_automation{
int next[maxn][4];
int end[maxn],fail[maxn];
int l,root,dp[maxn][maxn*2];
int newnode(){
for (int i=0;i<26;++i) next[l][i]=-1;
end[l]=fail[l]=0; return l++;
}
void init(){
l=0; root=newnode();
}
int idx(char c){
if (c=='A') return 0;
else if (c=='C') return 1;
else if (c=='G') return 2;
else return 3;
}
void ins(char buf[]){
int now=root,l=strlen(buf);
for (int i=0;i<l;++i){
int x=idx(buf[i]);
if (next[now][x]==-1)
next[now][x]=newnode();
now=next[now][x];
}end[now]=1;
}
void build(){
queue<int>q; fail[root]=root;
for (int i=0;i<4;++i)
if (next[root][i]!=-1){
q.push(next[root][i]);
fail[next[root][i]]=root;
}else next[root][i]=root;
while (!q.empty()){
int now=q.front(); q.pop();
for (int i=0;i<4;++i)
if (next[now][i]!=-1){
q.push(next[now][i]);
fail[next[now][i]]=next[fail[now]][i];
if (end[fail[next[now][i]]]) end[next[now][i]]=1;
}else next[now][i]=next[fail[now]][i];
}
}
void DP(int Case,char s[]){
memset(dp,127/3,sizeof(dp));
int HHH=dp[0][0];
dp[0][0]=0; int len=strlen(s);
for (int i=1;i<=len;++i)
for (int j=0;j<l;++j){
if (dp[i-1][j]==HHH) continue;
int now=idx(s[i-1]);
for (int k=0;k<4;++k)
if (!end[next[j][k]])
dp[i][next[j][k]]=min(dp[i][next[j][k]],dp[i-1][j]+(k!=now));
}
int ans=HHH;
for (int i=0;i<l;++i)
if (!end[i]) ans=min(ans,dp[len][i]);
if (ans==HHH) ans=-1;
printf("Case %d: %d\n",Case,ans);
}
}Ac;

int main(){
int Case=0;
while (scanf("%d",&n)!=EOF){
if (!n) break;
Case++;
Ac.init();
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%s",str);
Ac.ins(str);
}
Ac.build();
scanf("%s",str);
Ac.DP(Case,str);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OI