HDU 3746 Cyclic Nacklace

题目大意:给出一个原串长度至少为3,问怎么样在两边添加字符使得成为周期串(周期为2以上),要求添加的字符最少

思路:其实还是一道next数组的灵活运用而已,自己想了几种情况,枚举了下,再利用next数组求了几下..呵呵1A,爽.

1.已经是完整周期的

(1)abab

      如果含有周期的,那么直接输出0即可,注意先排除next为1的情况

2.还不是完整周期的

     (1)abcabcabca的情况

              如果next数组的两倍大于len的话,那么就是有重叠的,但是又不是完整周期的,直接用循环节减去取完模的数即可

     (2) abcdfeabc的情况

             如果next的两倍都还小于len的话,那么肯定是因为中间有空档,直接输出中间那一部分即可

     (3) abcd的情况

             next为1的话,直接输出原串的长度

 

这个规律其实我是做完这道题后的灵感一发:http://blog.csdn.net/kg_second/article/details/8861777

 

 

AC Program:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <queue>
#include <cassert>
typedef long long ll;
#define	clr(a)		memset((a),0,sizeof (a))
#define	rep(i,a,b)	for(int i=(a);i<(int)(b);i++)
#define	per(i,a,b)	for(int i=((a)-1);i>=(int)(b);i--)
#define	inf			(0x7fffffff)
#define	eps			1e-6
#define	MAXN		
#define MODN		(1000000007)
using namespace std;
char t[1000005];
int next[1000005];
void get_next(){
    next[1]=0;
    int k=0;
    int j=1;
    int len=strlen(t+1);     
    while(j<=len){
        if(k==0 || t[j]==t[k]){
            j++;
            k++;
            next[j]=k;        
        }             
        else{
            k=next[k];     
        } 
    }
}
int main(){
  int test;
  cin>>test;
  while(test--){
      scanf("%s",t+1);//从1开始  
      int len=strlen(t+1);         
      get_next();
      /*
      rep(i,0,len+2){
         cout<<next[i]<<" ";             
      }
      cout<<endl;*/
      int tmp=len%(len-(next[len+1]-1));
      if(tmp==0&&next[len+1]!=1){//如果含有周期的,那么直接输出0即可,注意先排除next为1的情况 
        cout<<0<<endl;
        continue;           
      }
      if((next[len+1])==1){//next为1的话,直接输出原串的长度 
        cout<<len<<endl;
        continue;           
      }
      
      if(2*(next[len+1]-1)<len){//如果next的两倍都还小于len的话,那么肯定是因为中间有空档,直接输出中间那一部分即可 
         cout<<len-2*(next[len+1]-1)<<endl;
         continue;              
      }
      else{//如果next数组的两倍大于len的话,那么就是有重叠的,但是又不是完整周期的,直接用循环节减去取完模的数即可 
         cout<<len-(next[len+1]-1)-tmp<<endl;     
      }
          
  };  
  //system("pause");
  return 0;
}


 

你可能感兴趣的:(HDU 3746 Cyclic Nacklace)