• bzoj3075[Usaco2013]Necklace


    题目链接:bzoj3075

    题目大意:

    给你一个长度为n的字符串A,再给你一个长度为m的字符串B,求至少在A中删去多少个字符才能使得B不是A的子串。注:该题只读入A和B,不读入长度,先读入A,再读入B。数据保证A和B中只含小写字母。


    题解:

    AC自动机+DP

    f[i][j]表示A串搞到第i位,树上走到j所能得到的串的最大长度。

    首先按B串建树,拿A来走。对于A串中的一个字符有两种选择,删与不删。如果删,那么树上的位置仍与当前一样;如果不删,就走。。注意判断一下当前节点合不合法就是了。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define maxm 1010
    
    struct node
    {
    	int son[26],fail;bool bk;
    }tr[maxm];
    int len,rt,l1,l2,f[maxm*10][maxm];
    char s1[maxm*10],s2[maxm];
    int new_node()
    {
    	len++;
    	memset(tr[len].son,0,sizeof(tr[len].son));
    	tr[len].fail=0;tr[len].bk=false; 
    	return len;
    }
    void bt()
    {
    	int now=rt,i;
    	for (i=0;i<l2;i++)
    	{
    		int x=s2[i]-'a';
    		if (!tr[now].son[x]) tr[now].son[x]=new_node();
    		now=tr[now].son[x];
    	}
    	tr[now].bk=true;
    }
    queue<int> q;
    void build_AC()
    {
    	int i;
    	for (i=0;i<26;i++)
    	 if (tr[rt].son[i])
    	 {
    		 tr[tr[rt].son[i]].fail=rt;
    		 q.push(tr[rt].son[i]);
    	 }else tr[rt].son[i]=rt;
    	while (!q.empty())
    	{
    		int x=q.front();q.pop();
    		int y=tr[x].fail;
    		for (i=0;i<26;i++)
    		  if (tr[x].son[i])
    		  {
    			  if (tr[y].son[i]) tr[tr[x].son[i]].fail=tr[y].son[i];
    			  else tr[tr[x].son[i]].fail=rt;
    			  q.push(tr[x].son[i]);
    		  }else tr[x].son[i]=tr[y].son[i];
    	}
    }
    int mymax(int x,int y) {return (x>y)?x:y;}
    int main()
    {
    	//freopen("a.in","r",stdin);
    	//freopen("a.out","w",stdout);
    	int i,j;
    	len=0;rt=new_node();
    	gets(s1);l1=strlen(s1);
    	gets(s2);l2=strlen(s2);
    	bt();build_AC();
    	memset(f,-1,sizeof(f));
    	f[0][rt]=0;f[0][tr[rt].son[s1[0]-'a']]=1;
    	for (i=0;i<l1-1;i++)
    	 for (j=1;j<=len;j++)
    	  if (f[i][j]!=-1)
    	  {
    		  int x=s1[i+1]-'a';
    		  int y=tr[j].son[x];
    		  if (!tr[y].bk) f[i+1][y]=mymax(f[i+1][y],f[i][j]+1);
    		  if (!tr[j].bk) f[i+1][j]=mymax(f[i+1][j],f[i][j]);
    	  }
    	int ans=-1;
    	for (i=1;i<=len;i++)
    	  if (f[l1-1][i]!=-1 && !tr[i].bk) ans=mymax(ans,f[l1-1][i]);
    	printf("%d
    ",l1-ans);
    	return 0;
    }


  • 相关阅读:
    20200323 Go语言基础
    20200313 图表工具与redis使用
    20200312 CMDB的磁盘数据查询
    20200311 CMDB的表设计
    20200320 代码发布之完结
    20200319 代码发布之任务发布钩子脚本
    Ubuntu 安装 MySQL 服务
    使用U盘重装系统(删除掉系统自带的Windows 10)
    Linux & Windows 上安装 Qt
    初次使用Tampermonkey脚本管理器
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527809.html
Copyright © 2020-2023  润新知