zoukankan      html  css  js  c++  java
  • [JZOJ6347]:ZYB玩字符串(DP+记忆化搜索) HEOI

    题目描述

      $ZYB$获得了一个神秘的非空字符串$p$。
      初始时,串$S$是空的。
      $ZYB$会执行若干次这样的操作:
      $1.$选取$S$中的一个任意的位置(可以是最前面或者最后面)
      $2.$在这个位置上插入一个完整的$p$,得到一个新的$S$。
      但是$ZYB$不小心把$p$弄丢了。
      他告诉你现在的$S$是什么,请帮他还原出可能的$p$。
      如果有多个$p$符合要求,选取长度最短的。
      如果仍然有多解,选取字典序最小的。


    输入格式

      从文件$string.in$中读入数据。
      这道题有多组数据,第一行一个数$T$,表示数据组数。
      对于每组数据,读入一行字符串,表示$S$。


    输出格式

      输出到文件$string.out$中。
      一共$T$行,每行一个字符串$p$,表示对应的答案。


    样例

    样例输入:

    1
    hhehellolloelhellolo

    样例输出:

    hello


    数据范围与提示

    样例解释:

      $S$为:
      $1.$
      $2.hello$
      $3.hhelloello$
      $4.hhelloelhellolo$
      $5.hhehellolloelhellolo$

    数据范围:

      前$20\%$:$|S|\leqslant 8$
      前$40\%$:$|S|\leqslant 20$
      前$60\%$:$|S|\leqslant 100,\sum|S|\leqslant 300$
      另有$10\%$:$S$是$p$等概率插入可行位置构造出来的。
      另有$10\%$:$p$的长度不超过$3$。
      $100\%$:$|S|\leqslant 200,T\leqslant 10,\sum|S|\leqslant 666$


    题解

    因为串$S$肯定有一段连续的是$p$(最后插进去的),所以可以枚举这个连续的串,再想办法判断就好了。

    考虑$DP$,定义怪怪的,设$dp[l][r]$表示在当前枚举的长度为$len$的情况下,区间$[l,r]$除了前$(r-l)%len$位匹配了整串前缀以外剩下的部分都匹配了是否可行。

    那么考虑转移,设$b$数组为当前$check$的这段区间:

      $\alpha.dp[l][r]|=dp[l][r-1]\&(s[j]==b[(j-i)%len+1])$:多匹配了一位。

      $\beta.dp[l][r]|=dp[i][j-k\times len]\&f[j-k\times len+1][j]$:后面有几段匹配了。

    由于$\beta$转移的上界为$\frac{N}{len}$,所以最终的时间复杂度为$\Theta(\sum\limits_{len|N}(N-len+1)\times N^2\times\frac{N}{len}=\Theta(N^4)$。

    不过可以对于每一个$p$,先判断一下其子集合法性,然后使用记忆化搜索即可。

    时间复杂度:$\Theta(N^4)$(但是远远达不到)。

    期望得分:$100$分。

    实际的分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    char ch[201];
    int n,a[201],b[201],ans[201];
    int dp[201][201];
    int mod(int x,int y){return x>y?mod(x-y,y):x;}
    bool dfs(int x,int l,int r)
    {
    	if(l>r)return 1;
    	if(dp[l][r]!=-1)return dp[l][r];
    	for(int mid=r-x;l<=mid;mid-=x)
    		if(dfs(x,l,mid)&&dfs(x,mid+1,r))
    			return dp[l][r]=1;
    	if(a[r]==b[mod(r-l+1,x)])return dp[l][r]=dfs(x,l,r-1);
    	return dp[l][r]=0;
    }
    bool judge(int x){for(int i=1;i<=x;i++)if(ans[i]>b[i])return 1;return 0;}
    int main()
    {
    	int T;scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%s",ch+1);
    		n=strlen(ch+1);
    		for(int i=1;i<=n;i++)a[i]=ch[i]-'a'+1;
    		for(int i=1;i<=n;i++)
    		{
    			if(n%i)continue;bool res=0;
    			memset(ans,0,sizeof(ans));
    			for(int j=1;j<=n-i+1;j++)
    			{
    				memset(dp,-1,sizeof(dp));
    				for(int k=1;k<=i;k++)b[k]=a[j+k-1];
    				if(dfs(i,1,n)&&(!ans[1]||judge(i)))
    					for(int k=1;k<=i;k++)ans[k]=b[k];
    			}
    			if(ans[1]){for(int k=1;k<=i;k++)printf("%c",(char)(ans[k]+'a'-1));puts("");break;}
    		}
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    可爱的中国电信 请问我们的电脑还属于我们自己吗?
    了解客户的需求,写出的代码或许才是最优秀的............
    DELPHI DATASNAP 入门操作(3)简单的主从表的简单更新【含简单事务处理】
    用数组公式获取字符在字符串中最后出现的位置
    在ehlib的DBGridEh控件中使用过滤功能(可以不用 MemTableEh 控件 适用ehlib 5.2 ehlib 5.3)
    格式化json返回的时间
    ExtJs中使用Ajax赋值给全局变量异常解决方案
    java compiler level does not match the version of the installed java project facet (转)
    收集的资料(六)ASP.NET编程中的十大技巧
    收集的资料共享出来(五)Asp.Net 权限解决办法
  • 原文地址:https://www.cnblogs.com/My-tiantian/p/11850230.html
Copyright © 2011-2022 走看看