zoukankan      html  css  js  c++  java
  • ZROI2018提高day1t3

    传送门

    分析

    考场上想到了先枚举p的长度,在枚举这个长度的所有子串,期望得分40~50pts,但是最终只得了20pts,这是因为我写的代码在验证中总是不断删除s'中的第一个p,而这种方式不能解决形如ababaa的字符串。于是我们考虑满分做法。设dp[i][j]表示在当前的p的情况下s的[i,j]位置是否满足。满足是指这一段区间只由p构成或者一部分只由p构成,另一部分则是p的前缀。对于位置j的字符可能有两种情况:

      1.和之后数个字符拼成一段,转移:

        dp[i][j]|=(dp[i][j-1]&(s[j]==p[(j-i)%len+1]))。

      2.和之前的一段字符拼在一起,中间已经有k个p,转移:

        dp[i][j]|=(dp[i][j-k*len]&dp[j-k*len+1][j])。

    然后我们使用记忆化搜索转移即可。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    const int inf = 1e9+7;
    int dp[300][300],n,m,cnt,len;
    char s[300],t[300],ans[300];
    inline int dfs(int le,int ri){
          if(le>ri)return 1;
          if(dp[le][ri]!=-1)return dp[le][ri];
          dp[le][ri]=0;
          if(dfs(le,ri-1)&&s[ri]==t[(ri-le)%len+1])dp[le][ri]|=1;
          for(int i=ri-len;i>=le;i-=len)
            if(dfs(le,i)&&dfs(i+1,ri))dp[le][ri]|=1;
          return dp[le][ri];
    }
    inline void getmin(){
          if(cnt>len){
              for(int i=1;i<=len;i++)ans[i]=t[i];
              cnt=len;
              return;
          }
          for(int i=1;i<=cnt;i++)
            if((ans[i]-'0')<(t[i]-'0'))return;
              else if((ans[i]-'0')>(t[i]-'0'))break;
          for(int i=1;i<=cnt;i++)ans[i]=t[i];
    }
    int main(){
          int i,j,k,T;
          scanf("%d",&T);
          while(T--){
              cnt=inf;
              scanf("%s",t);
              n=strlen(t);
              for(i=1;i<=n;i++)s[i]=t[i-1];
              for(i=1;i<=min(n,cnt);i++)
                if(!(n%i))for(j=1;j+i-1<=n;j++){
                    memset(dp,-1,sizeof(dp));m=i;
                    for(k=1;k<=i;k++)t[k]=s[j+k-1];
                    len=i;if(dfs(1,n))getmin();
                }
              for(i=1;i<=cnt;i++)cout<<ans[i];
              puts("");
          }
          return 0;
    }
  • 相关阅读:
    uniapp
    vue -element admin 修改request,headers添加参数
    uniapp
    css
    uniapp
    uniapp
    vue
    vue
    vue -element 修复select下拉框在移动端需要点击两次才能选中的问题
    vue
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9570047.html
Copyright © 2011-2022 走看看