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

然后今天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. Algebrizer

    Microsoft SQL Server 2012 Internals 把 SQL 语句的处理分为四个阶段,分别是 解析.绑定.优化.执行,如图所示:     解析(Parse)主要是语法分析,比较简 ...

  2. TextOut与DrawText的区别

    BOOL TextOut( HDC hdc, // 句柄 int nXStart, // 字符串的开始位置 x坐标 int nYStart, // 字符串的开始位置 y坐标 LPCTSTR lpStr ...

  3. 移动web——bootstrap模板

    基本概念 1.bootstrap就是在媒体查询技术出现以后才开始出现的 2.此技术使响应式开发变得十分轻松,最大特点就是栅格系统(什么设备上如何显示)以及响应式工具(是否可见) 基本模板 <!D ...

  4. HyperLink的使用

    <asp:HyperLink ID="Hyperlink2" NavigateUrl='<%# string.Format("AddOrganizition. ...

  5. Redis 之仿微博demo

    一.用户注册登录 include './header.php'; include './function.php'; $username = p('username'); $password = p( ...

  6. PHP 魔术方法浅谈

    php中把以两个下划线(__)开头的方法称之为魔术方法.魔术方法包括: __construct()    类的构造方法  构建方法时被调用 __destruct()      类的析构方法  明确销毁 ...

  7. 后台取前台input标签值方法

    直接在实体类中增加一个get set方法就可以实现取到value值

  8. swift--如何设置子视图alpha不同于父视图

    //1.2加入商家标题评分容器 let titleWarp=UIView(frame: CGRectMake(, , screenObject.width, )); titleWarp.backgro ...

  9. 原型&&原型链一语道破梦中人

    一直对原型和原型链模模糊糊,今天看到一句话,通过这句话再结合我目前对原型和原型链的理解算是让我对原型和原型链有一个更清醒的认识;并且记忆更加深刻; 任何一个对象都有一个隐式原型:__proto__属性 ...

  10. 七牛直播云-m3u8格式直播

    直播架构 业务服务器:负责协调直播类应用的业务逻辑 创建直播房间 返回直播房间播放地址列表 关闭直播房间 LiveNet 实时流网络:负责流媒体的分发.直播流的创建.查询等相关操作 采集端:负责采集和 ...