HDU 4850 Wow! Such String!(构造推理)

来源:互联网 发布:山姆 知乎 编辑:程序博客网 时间:2024/05/17 09:17

题意:给定长度n 找到一个满足
1.长度为n
2.全为小写字母
3.长度>=4的子串只出现一次 的字符串 没有则输出Impossible

开始的时候就一直觉得这道题有规律 纠结于找不到这样串的临界点究竟是什么时候……
后来发现我真的想多了 = =就一直推下去 推不到就是Impossible

具体推理过程就是用vis四维数组标记连续的串是否出现:
vis[i][j][k][l] 就是表示’a’+i ‘a’+j ‘a’+k ‘a’+l 是否出现

然后前面26*4都用相同字母aaaabbbbcccc……zzzz这样填充
之后一个字母一个字母推
每次用 最大的字母 且 加上该字母后连续串在vis数组出现过 的填充
填充完在vis数组中将该字母加上之前三个字母的连续串在vis数组中置1
用flag标记 当某个位置取得最小字母时都无法填充时 说明不可以组成这样的串

某一段字母样例为:
aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz
yzzyyzyzyyyxzzzxzzyxzyzxzyyxyzzxyzyxyyzxyyxxzzxxzyxxyzxx

首先,如果反向推也是可行的,先从’z’~’a’填充,然后填充最小的字母zzzz…aaaabaab…
但是,如果’a’~’z’填充,然后每次选择最小的字母填充是不可行的,为什么呢?
先看一下如果用这样的想法最多的字符串:

pic1
可以明显看出,’a’过多的占用位置导致每4个位置的最后一个位置没有办法放下别的字母,如果需要继续放,必须改变第三个字母的再继续放入,想想就很麻烦
使用’z’~’a’的顺序用最大字母填充后面的位置能够改善这样的情况。

但是到底为什么这样可以出结果还是不知道啊

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>using namespace std;const int N = 26*26*26*26+10;const int N1 = 26*4;int vis[30][30][30][30];char s[N];int main() {    int n;    while(~scanf("%d",&n)) {        memset(vis,0,sizeof(vis));        memset(s,0,sizeof(s));        int cnt=0;        char c='a';        int temp=n>N1?N1:n;        for(int i=0; i<temp; i++) {            if(cnt>=4) {                cnt=0;                c++;            }            s[i]=c;            cnt++;        }        int flag=0;        if(n>N1) {            for(int i=3; i<N1; i++) {                vis[s[i-3]-'a'][s[i-2]-'a'][s[i-1]-'a'][s[i]-'a']=1;            }            for(int i=N1; i<n; i++) {                flag=0;                for(char j='z'; j>='a'; j--) {                    if(vis[s[i-3]-'a'][s[i-2]-'a'][s[i-1]-'a'][j-'a']==0) {                        flag=1;                        s[i]=j;                        vis[s[i-3]-'a'][s[i-2]-'a'][s[i-1]-'a'][j-'a']=1;                        break;                    }                }                if(!flag) {                    break;                }            }        } else flag=1;        if(!flag) puts("Impossible");        else printf("%s\n",s);    }}
0 0
原创粉丝点击