今天下午讨论了一下校赛的题,最终最终拍板,把校赛的题目定下来了。

然后今天A掉了4个AC自己主动机的题目。最终完毕了AC自己主动机专辑里面的15个题。至此AC自己主动机全然结束。

明天开启线段树专题。

。。。。

------------------------------------------------------------------------------------------------------------------------------------

1,,hdu-2457-DNA repair

题目:给出一些不合法的模式DNA串,给出一个原串,问最少须要改动多少个字符,使得原串中不包括非法串

做法:把病毒串做成一个trie树。

DP[i][j]:长度为i,在trie树上的状态为j。须要改变的最少的字符的个数。

dp[i][j]=dp[i-1][k]+转移费用。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
#define LL __int64
#define maxn 55
const int maxnode=55*21;
const int childnum=5;
const int mod=1000000007;
const int INF=99999999;
struct ac_tree
{
int chd[maxnode][childnum];
int val[maxnode];
int fail[maxnode];
int key[1<<11];
int Q[maxnode];
int ID[128];
int sz;
int dp[1100][maxnode];
void init()
{
fail[0]=0;
for(int i=0;i<childnum;i++)
{
ID[i]=i;
}
ID['A']=1;ID['G']=2;
ID['C']=3;ID['T']=4;
}
void reset()
{
memset(chd,0,sizeof(chd));
sz=1;
}
void insert(char str[],int k)
{
int p=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int c=ID[str[i]];
if(!chd[p][c])
{
memset(chd[sz],0,sizeof(chd[sz]));
val[sz]=0;
chd[p][c]=sz++;
}
p=chd[p][c];
}
val[p]=k;
}
void ac_build()
{
int *s=Q,*e=Q;
for(int i=1;i<childnum;i++)
{
if(chd[0][i])
{
fail[chd[0][i]]=0;
*e++=chd[0][i];
}
}
while(s!=e)
{
int u=*s++;
if(val[fail[u]])val[u]+=val[fail[u]];
for(int i=1;i<childnum;i++)
{
int &v=chd[u][i];
if(v)
{
*e++=v;
fail[v]=chd[fail[u]][i];
// val[v]=(val[v]+val[fail[v]]);
}
else v=chd[fail[u]][i];
}
}
}
int work(char str[])
{
int len=strlen(str);
int i,j,k;
for(i=0;i<=len;i++)
for(j=0;j<sz;j++)dp[i][j]=INF;
dp[0][0]=0;
int cr,x;
for(i=0;i<len;i++)
{
for(j=0;j<sz;j++)
{
if(dp[i][j]==INF)continue;
for(k=1;k<childnum;k++)
{
cr=chd[j][k];
if(val[cr])continue;
x=dp[i][j];
if(k!=ID[str[i]])x++;
dp[i+1][cr]=min(dp[i+1][cr],x);
}
}
}
int maxx=INF;
for(j=0;j<sz;j++)
{
maxx=min(maxx,dp[len][j]);
}
if(maxx==INF)cout<<"-1"<<endl;
else cout<<maxx<<endl;
}
}AC;
char tmp[1550];
int main()
{
AC.init();
int n,m,k,x;
int T;
T=0;
while(~scanf("%d",&n)&&(n))
{
T++;
AC.reset();
for(int i=1;i<=n;i++)
{ scanf("%s",tmp);
AC.insert(tmp,1);
}
AC.ac_build();
scanf("%s",tmp);
printf("Case %d: ",T);
AC.work(tmp);
}
return 0;
}

2,zoj-3228-Searching the String

题目大意:给出一个字符串和若干个单词。问这些单词在字符串里面出现了多少次。单词前面为0表示这个单词可重叠出现。1为不可重叠出现。

做法: 可重叠的非常优点理,就是AC自己主动机处理。不可重叠的就记录下上次这个单词出现的位置。假设上次出现的位置加上这个单词的长度小于等于当前位置的话,那么这个单词的次数就加一。否则就不加。

注意:可能存在两个字符串相等,比較坑爹。。。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
#define LL __int64
#define maxn 55
const int maxnode=6*110000;
const int childnum=27;
const int mod=1000000007;
const int INF=99999999;
struct ac_tree
{
int chd[maxnode][childnum];
int val[maxnode][2];
int fail[maxnode];
int last[maxnode];
int num[maxnode][2];
int *ans[maxnode];
int key[1<<11];
int Q[maxnode];
int ID[128];
int sz;
void init()
{
fail[0]=0;
for(int i=0;i<childnum;i++)
{
ID[i+'a']=i+1;
}
}
void reset()
{
memset(chd,0,sizeof(chd));
memset(num,0,sizeof(num));
sz=1;
}
void insert(char str[],int k,int tt)
{
int p=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int c=ID[str[i]];
if(!chd[p][c])
{
memset(chd[sz],0,sizeof(chd[sz]));
val[sz][tt]=0;
chd[p][c]=sz++;
}
p=chd[p][c];
}
val[p][tt]=len;
last[p]=-1;
ans[k]=&num[p][tt];
}
void ac_build()
{
int *s=Q,*e=Q;
for(int i=1;i<childnum;i++)
{
if(chd[0][i])
{
fail[chd[0][i]]=0;
*e++=chd[0][i];
}
}
while(s!=e)
{
int u=*s++;
//if(val[fail[u]])val[u]+=val[fail[u]];
for(int i=1;i<childnum;i++)
{
int &v=chd[u][i];
if(v)
{
*e++=v;
fail[v]=chd[fail[u]][i];
// val[v]=(val[v]+val[fail[v]]);
}
else v=chd[fail[u]][i];
}
}
}
int work(char str[],int n)
{
int len=strlen(str);
int root=0,key,tp,x;
for(int i=0;i<len;i++)
{
tp=ID[str[i]];
root=chd[root][tp];
key=root;
while(key!=0)
{
if(val[key][0]!=0)num[key][0]++;
if(val[key][1]!=0)
{
if(last[key]<=i-val[key][1])
{
num[key][1]++;
last[key]=i;
}
}
key=fail[key];
}
}
for(int i=1;i<=n;i++)
printf("%d\n",*ans[i]);
puts("");
}
}AC;
char tmp[1550];
char as[110000];
int main()
{
AC.init();
int n,m,k,x;
int T;
T=0;
while(~scanf("%s",as))
{
T++;
AC.reset();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d %s",&k,tmp);
AC.insert(tmp,i,k);
}
AC.ac_build();
printf("Case %d\n",T);
AC.work(as,n);
}
return 0;
}

3,hdu-3341-Lost's revenge

抄的解题报告,感觉说的非常具体。我就不赘余了。

 题意:给出一些病毒串,一个原串,问怎么调整原串的顺序使得跟最多的病毒串匹配



    抄解题报告:

    自己主动机+DP。设主串有na个A、nc个C、ng个G、nt个T,于是题意转化为用na个A、

    nc个C、ng个G、nt个T生成一个新串,使模式串匹配次数最大。

先将模式串生成自己主动机

    〔trie图〕,然后在这上面进行DP。状态可表示为dp[d,s],d为自己主动机状态。

    s表示由ma个A、mc个C、mg个G、mt个T的生成串

    〔s可表示为ma*(nc+1)*(ng+1)*(nt+1)+mc*(ng+1)*(nt+1)+mg*(nt+1)+mt〕。

    转移为O(4),总复杂度O(500*11^4*4) 

    

    那种表示方法就是变进制吧



    直接DP(root,s)会超时

    Qinz说这题卡时紧

    我用他的那种dfs才干过。他是先dfs枚举出状态,然后对这个状态递推计算。好快



    比較奇妙,不用管顺序的,就记录个数

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
#define LL __int64
#define maxn 55
const int maxnode=51*10;
const int childnum=5;
const int mod=1000000007;
const int INF=99999999;
struct ac_tree
{
int chd[maxnode][childnum];
int val[maxnode];
int fail[maxnode];
int Q[maxnode];
int ID[128];
int sz;
int dp[maxnode][14642];
void init()
{
fail[0]=0;
for(int i=0;i<childnum;i++)
{
ID[i+'a']=i+1;
}
ID['A']=1;ID['T']=2;
ID['G']=3;ID['C']=4;
}
void reset()
{
memset(chd,0,sizeof(chd));
memset(val,0,sizeof(val));
sz=1;
}
void insert(char str[],int k)
{
// cout<<str<<endl;
int p=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int c=ID[str[i]];
if(!chd[p][c])
{
memset(chd[sz],0,sizeof(chd[sz]));
val[sz]=0;
chd[p][c]=sz++;
}
p=chd[p][c];
}
val[p]+=k;
//cout<<p<<" "<<val[p]<<endl;
}
void ac_build()
{
int *s=Q,*e=Q;
for(int i=1;i<childnum;i++)
{
if(chd[0][i])
{
fail[chd[0][i]]=0;
*e++=chd[0][i];
}
}
while(s!=e)
{
int u=*s++;
if(val[fail[u]])val[u]+=val[fail[u]];
for(int i=1;i<childnum;i++)
{
int &v=chd[u][i];
if(v)
{
*e++=v;
fail[v]=chd[fail[u]][i];
// val[v]=(val[v]+val[fail[v]]);
}
else v=chd[fail[u]][i];
}
}
}
int work(char str[])
{
int num[5];
memset(num,0,sizeof(num));
int len=strlen(str);
for(int i=0;i<len;i++)num[ID[str[i]]]++;
dp[0][0]=0;
int tai,cr;
int sum[6];
sum[5]=1;
sum[4]=num[4]+1;
sum[3]=(num[3]+1)*sum[4];
sum[2]=(num[2]+1)*sum[3];
sum[1]=(num[1]+1)*sum[2];
int a[5],i,j;
int pt;
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
for(a[1]=0;a[1]<=num[1];a[1]++)
for(a[2]=0;a[2]<=num[2];a[2]++)
for(a[3]=0;a[3]<=num[3];a[3]++)
for(a[4]=0;a[4]<=num[4];a[4]++)
{
if(a[1]+a[2]+a[3]+a[4]>=len)break;
tai=0;
for(i=1;i<=4;i++)tai+=a[i]*sum[i+1];
for(i=0;i<sz;i++)
{
if(dp[i][tai]==-1)continue;
for(j=1;j<childnum;j++)
{
if(a[j]+1>num[j])continue;
cr=chd[i][j];
pt=tai+sum[j+1];
// if(dp[cr][pt]==-1)dp[cr][pt]=dp[i][tai];
dp[cr][pt]=max(dp[cr][pt],dp[i][tai]+val[cr]);
// cout<<i<<" "<<j<<"->"<<cr<<" "<<pt<<" "<<dp[cr][pt]<<endl;
}
}
}
pt=num[1]*sum[2]+num[2]*sum[3]+num[3]*sum[4]+num[4];
int maxx=-1;
for(i=0;i<sz;i++)
{
maxx=max(maxx,dp[i][pt]);
}
cout<<maxx<<endl;
}
}AC;
char tmp[1550];
char as[110000];
int main()
{
AC.init();
int n,m,k,x;
int T;
T=0;
while(~scanf("%d",&n)&&n)
{
T++;
AC.reset();
for(int i=1;i<=n;i++)
{
scanf("%s",tmp);
AC.insert(tmp,1);
}
AC.ac_build();
scanf("%s",as);
printf("Case %d: ",T);
AC.work(as);
}
return 0;
}

4,hdu-3247-Resource Archiver

题意:

给你 n 个串。和 m 个病毒串。要把这 n 个串
连起来来,能够重叠,但不能包括 m 个病毒串
中的随意一个。求把 n 个串连起来的最小长度。

做法:这个题目憋了我非常长时间,一直不知道怎么样处理。后来经过翻阅博客。最终悟出来点。

把病毒串和非病毒串都标记在trie树上处理。然后病毒串的地方标记为病毒串,非病毒串的地方标记为是哪一个串。

状态压缩一下。

然后从每一个非病毒串的结尾開始bfs。

map[i][j]:从i字符串的结尾。到j字符串的结尾的最短路径是多少。

然后就能够DP了。

dp[i][j]:已用的字符串为i状态,在trie树上的点为j状态。的最短路径。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
#define LL __int64
#define maxn 205
const int maxnode=100001;
const int childnum=3;
const int mod=1000000007;
const int INF=99999999;
struct list
{
int st;
int x;
}pp,qq;
struct ac_tree
{
int chd[maxnode][childnum];
int val[maxnode];
int fail[maxnode];
int Q[maxnode];
int var[maxnode];
int vis[maxnode];
int dist[maxnode];
int st[maxn];
int ID[128];
int sz;
int maps[maxn][maxn];
int ns;
int dp[1<<11][maxn];
void init()
{
fail[0]=0;
for(int i=0;i<childnum;i++)
{
ID[i+'a']=i+1;
}
ID['0']=1;ID['1']=2;
}
void reset()
{
memset(chd,0,sizeof(chd));
memset(val,0,sizeof(val));
memset(var,0,sizeof(var));
memset(maps,-1,sizeof(maps));
sz=1;
}
void insert(char str[],int k,int ps)
{
// cout<<str<<endl;
int p=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int c=ID[str[i]];
if(!chd[p][c])
{
memset(chd[sz],0,sizeof(chd[sz]));
val[sz]=0;
chd[p][c]=sz++;
}
p=chd[p][c];
}
if(ps==0)
{
val[p]=k;
var[p]=0;
}
else var[p]=1;
//cout<<p<<" "<<val[p]<<endl;
}
void ac_build()
{
int *s=Q,*e=Q;
for(int i=1;i<childnum;i++)
{
if(chd[0][i])
{
fail[chd[0][i]]=0;
*e++=chd[0][i];
}
}
while(s!=e)
{
int u=*s++;
//if(val[fail[u]]==-1)val[u]=-1;
for(int i=1;i<childnum;i++)
{
int &v=chd[u][i];
if(v)
{
*e++=v;
fail[v]=chd[fail[u]][i];
val[v]=(val[v]|val[fail[v]]);
var[v]=(var[v]|var[fail[v]]);
}
else v=chd[fail[u]][i];
}
}
}
int bfs(int u)
{
queue<int>que;
while(!que.empty())que.pop();
int x=st[u];
que.push(x);
memset(dist,-1,sizeof(dist));
dist[x]=0;
while(!que.empty())
{
x=que.front();
que.pop();
for(int i=1;i<childnum;i++)
{
int y=chd[x][i];
if(var[y])continue;
if(dist[y]<0)
{
dist[y]=dist[x]+1;
que.push(y);
}
}
}
for(int i=0;i<ns;i++)
{
maps[u][i]=dist[st[i]];
//cout<<u<<"->"<<i<<"="<<maps[u][i]<<endl;
}
}
int work(int n)
{
st[0]=0;
ns=1;
for(int i=0;i<sz;i++)
if(val[i])
{
st[ns++]=i;
//cout<<ns-1<<" "<<val[st[ns-1]]<<endl;
}
for(int i=0;i<ns;i++)bfs(i);
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
int cr;
for(int i=0;i<(1<<n);i++)
{
for(int j=0;j<ns;j++)
{
if(dp[i][j]<0)continue;
for(int k=0;k<ns;k++)
{
if(maps[j][k]<0)continue;
cr=i|val[st[k]];
if(dp[cr][k]==-1)dp[cr][k]=dp[i][j]+maps[j][k];
else dp[cr][k]=min(dp[cr][k],dp[i][j]+maps[j][k]);
// cout<<cr<<" "<<k<<" "<<dp[cr][k]<<endl;
}
}
}
int minn=-1;
cr=(1<<n)-1;
for(int i=0;i<ns;i++)
{
if(dp[cr][i]==-1)continue;
if(minn<0)minn=dp[cr][i];
minn=min(minn,dp[cr][i]);
}
cout<<minn<<endl;
} }AC;
char tmp[1550];
int main()
{
AC.init();
int n,m,k,x;
int T;
T=0;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
AC.reset();
for(int i=1;i<=n;i++)
{
scanf("%s",tmp);
AC.insert(tmp,1<<(i-1),0);
}
for(int i=1;i<=m;i++)
{
scanf("%s",tmp);
AC.insert(tmp,1,1);
}
AC.ac_build();
AC.work(n);
}
return 0;
}

每日总结-05-19(AC自己主动机结束)的更多相关文章

  1. zoj 3430 Detect the Virus(AC自己主动机)

    Detect the Virus Time Limit: 2 Seconds      Memory Limit: 65536 KB One day, Nobita found that his co ...

  2. [POJ 1204]Word Puzzles(Trie树暴搜&amp;AC自己主动机)

    Description Word puzzles are usually simple and very entertaining for all ages. They are so entertai ...

  3. hdu4057 Rescue the Rabbit(AC自己主动机+DP)

    Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

  4. POJ 2778 DNA Sequence (AC自己主动机 + dp)

    DNA Sequence 题意:DNA的序列由ACTG四个字母组成,如今给定m个不可行的序列.问随机构成的长度为n的序列中.有多少种序列是可行的(仅仅要包括一个不可行序列便不可行).个数非常大.对10 ...

  5. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

  6. 【UVA】1449-Dominating Patterns(AC自己主动机)

    AC自己主动机的模板题.须要注意的是,对于每一个字符串,须要利用map将它映射到一个结点上,这样才干按顺序输出结果. 14360841 1449 option=com_onlinejudge& ...

  7. POJ 3691 &amp; HDU 2457 DNA repair (AC自己主动机,DP)

    http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...

  8. HDU 2896 病毒侵袭 AC自己主动机题解

    本题是在text里面查找key word的增强版.由于这里有多个text. 那么就不能够简单把Trie的叶子标志记录改动成-1进行加速了,能够使用其它技术.我直接使用个vis数组记录已经訪问过的节点, ...

  9. NYOJ 1085 数单词 (AC自己主动机模板题)

    数单词 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 为了可以顺利通过英语四六级考试,如今大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中能够通过六 ...

随机推荐

  1. T-SQL查询基础

    今天来带大家了解下在sql server 中的查询机制 使用select语句进行查询 1.查询所有的数据行和列 select * from student 2.查询部分行和列 select scode ...

  2. nodejs全局安装路径的位置

    一般nodejs安装在默认的C盘,如果不知道安装在哪里,可以打开控制面板-系统和安全-系统-高级配置中找到 所谓全局安装: 是指安装在node中node_module的根目录里,可以在电脑的任何位置调 ...

  3. node.js安装及其环境配置

    nodejs: 实际上是采用google的chrome浏览器V8引擎,由C++编写的 本质上是一个javascript的运行环境 浏览器引擎可以解析js代码 nodejs可以解析js代码,没有浏览器端 ...

  4. linux使用mount命令挂载、umount命令取消挂载

    一.mount挂载目录方式: mount 挂载目录 磁盘目录 二.umout取消挂载目录方式: 1.umout 磁盘目录 2.umout 挂载目录 3.umout 磁盘目录 挂载目录 如下图

  5. IOS7升级攻略

    1) Select the main view, set the background color to black (or whatever color you want the status ba ...

  6. C# null

    var t0est = Convert.ToString(""+null);//结果"" var t1est = ("" + null).T ...

  7. Windows如何正确的修改administrator用户名

    无论是服务器还是电脑.修改默认的administrator的用户总是好的.话不多少.直接上图 1.win+r  输入:gpedit.msc 2.按照我下图的圈圈找到重命名系统管理员账户并自定义 3.重 ...

  8. 谷歌浏览器中a:link设置字体颜色无效问题

    <div id="box"> <a href="#">111111</a> <a href=""& ...

  9. PAT (Advanced Level) Practice(更新中)

    Source: PAT (Advanced Level) Practice Reference: [1]胡凡,曾磊.算法笔记[M].机械工业出版社.2016.7 Outline: 基础数据结构: 线性 ...

  10. Jenkins+Ant+Jmeter自动化集成测试实例

    通过学习Jmeter自动化测试,接触到了Ant命令和其构建文件build.xml文件的编写,与此同时,通过将测试项目集成在jenkins上,进一步学习了jenkins的一些环境配置知识.以下是自己的初 ...