196D The Next Good String

传送门

题目大意

给定n和一个字符串,求一个新字符串使得这个字符串不存在长度大于等于n的回文子串且在字典序大于原串的情况下最小。

分析

我们知道如果有一个长度为n+2的回文串,那它一定由一个长度为n的回文串构成,所以我们只寻找长度为n和n+1的回文串。我们枚举每个位置的字母使最终字符串满足条件即可,有一些处理详见代码(注意判断回文串的相减部分)。

代码

#include
#include
#include
#include<string>
#include
#include
#include
#include
#include
#include
#include
#include<set>
#include
#include
using namespace std;
#define uli unsigned long long
const uli HASH = 131313;
uli hsh[400100],h1[400100],h2[400100];
char s[400100],ans[400100];
int n,m;
inline bool add(int x){
      while(s[x]=='z'){
          s[x]='a';
          x--;
      }
      if(x<0)return 0;
      s[x]++;
      return 1;
}
inline bool ok(int le,int ri){
      if(le<1)return 1;
      if((h1[ri]-h1[le-1]*hsh[ri-le+1])*hsh[le-1]==h2[ri]-h2[le-1])
        return 0;
      return 1;
}
inline bool dfs(int wh,int is){
      if(wh==n)return 1;
      for(ans[wh]=(is?s[wh]:'a');ans[wh]<='z';ans[wh]++){
          h1[wh+1]=h1[wh]*HASH+(ans[wh]-'a');
          h2[wh+1]=h2[wh]+(ans[wh]-'a')*hsh[wh];
          if(ok(wh-m+2,wh+1)&&ok(wh-m+1,wh+1)&&
          dfs(wh+1,is&(ans[wh]==s[wh])))
            return 1;
      }
      return 0;
}
int main(){
      int i,j,k;
      scanf("%d",&m);
      scanf("%s",s);
      n=strlen(s);
      hsh[0]=1;
      for(i=1;i<=n+10;i++)
        hsh[i]=hsh[i-1]*HASH;
      if(m==1||!add(n-1)){
          puts("Impossible");
          return 0;
      }
      if(dfs(0,1)){
          for(i=0;ians[i];
        puts("");
      }else puts("Impossible");
      return 0;
}

 

转载于:https://www.cnblogs.com/yzxverygood/p/9413873.html

你可能感兴趣的:(196D The Next Good String)