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);
}
}
都是傻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);
}
}
相关文章推荐
- WHOIS类的修改版
- Begins and tests
- USACO2013 Nov. Gold T3,一道集合DP
- 数学-素数筛及其拓展
- 最大流模板
- 计算几何模板
- 各种树模板(splay,线段树,可持久化线段树...)
- 上下界网络流初探
- 二分图匹配模板
- CCC 2015 总结&回顾
- 【数论】组合数求模
- 【计算几何】POJ 2318 & POJ 2398
- ACM/ICPC World Finals 2013 A Self-Assembly
- NOI2015结束,从此我要全力以赴奋战OI
- 基础数据结构代码及其应用
- BZOJ 2440 & 2301 莫比乌斯应用
- 此博客从今日起正式启用
- APIO 2013行记
- SJTUSC 行记
- C++例子:setprecision