KMP

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <string>
  7 #include <deque>
  8 #include <vector>
  9 #include <set>
 10 #include <map>
 11 #include <cmath>
 12 using namespace std;
 13 #define  ll long long 
 14 #define  N  100009
 15 #define  gep(i,a,b)   for(int i=a;i<=b;i++)
 16 #define  gep1(i,a,b)  for(int i=a;i>=b;i--)
 17 #define  gepp(i,a,b)  for(ll i=a;i<=b;i++)
 18 #define  gepp1(i,a,b) for(ll i=a;i>=b;i--)
 19 #define  mem(a,b)     memset(a,b,sizeof(a))
 20 #define  ph  push_back
 21 #define  lowbit(x)  x&(-x)
 22 #define  P  pair<int,bool> 
 23 int c[100];
 24 char  p[100];
 25 void get(){
 26    mem(c,0);
 27     int i=0,j=-1;
 28     c[0]=-1;
 29     while(p[i]){
 30         if(j==-1||p[i]==p[j]){
 31             c[++i]=++j;
 32         }
 33         else
 34         {j=c[j];
 35         }
 36     }
 37     /*
 38     for(int i=0;i<=strlen(p);i++){//有==
 39         printf("%d ",c[i]);
 40     }
 41     
 42     azcaz
 43     -1 0 0 0 1 2
 44        c[i]: p[0:i)中前缀和后缀的最长公共在前缀的右边界(+1)
例如:
azcazaz
a -1
az 0
azc 0
azca 0
azcaz 1 :在azca中前缀a后缀 a 为最长公共,而a在前缀的右边界+1的索引为1(z的位置)
azcaza 2 : 在azcaza中前缀az后缀az 为最长公共 ,而az在前缀的右边界+1的索引为2(c的位置)
azcazaz 1 :在azcazaz中前缀a后缀a为最长公共,而a在前缀的右边界+1的索引为1(z的位置)
azcazaz_ 2 :在azcazaz中前缀az后缀az为最长公共,而az在前缀的右边界+1的索引为2(c的位置) 45 printf("\n"); 46 */ 47 48 }
p在s中第一次出现的位置
49 int kmp(){ 50 int i,j; 51 i=j=0; 52 get(); 53 while(i<n&&j<m){ 54 if(j==-1||s[i]==p[j]){ 55 i++,j++; 56 } 57 else 58 { 59 j=c[j]; 60 } 61 if(j==m) 62 { 63 return i-m; 64 } 65 } 66 return -1; 67 /* 68 1 2 1 2 3 1 2 3 1 3 2 1 2//初始下标为0 69 1 2 3 1 3 70 5 71 1 2 1 2 3 1 2 3 1 3 2 1 2 72 1 2 3 2 1 73 -1 74 */ 75 }
p在s中出现的次数 不同p可有交集
76 int kmp(){ 77 int lens=strlen(s); 78 int lenp=strlen(p); 79 int i=0,j=0; 80 int ans=0; 81 get(); 82 while(i<lens&&j<lenp){ 83 if(j==-1||s[i]==p[j]){ 84 i++; 85 j++; 86 87 } 88 else 89 { 90 j=c[j]; 91 } 92 if(j==lenp){ 93 ans++; 94 j=c[j]; 95 } 96 97 } 98 return ans; 99 /* 100 AZA 101 AZAZAZA 102 3 103 */ 104 }
p在s中出现的次数,不同p无交集
105 int kmp(){ 106 int lens=strlen(s); 107 int lenp=strlen(p); 108 int i=0,j=0; 109 int ans=0; 110 get(); 111 while(i<lens&&j<lenp){ 112 if(j==-1||s[i]==p[j]){ 113 i++; 114 j++; 115 116 } 117 else 118 { 119 j=c[j]; 120 } 121 if(j==lenp){ 122 ans++; 123 j=0; 124 } 125 126 } 127 return ans; 128 /* 129 aaaaaa 130 aa 131 3 132 */ 133 134 } 135 字符串后面添加元素令字符串为周期字符串 136 while(t--) 137 { 138 scanf("%s",p); 139 get(); 140 int len2=strlen(p);
abcab x:3
abcabc x:3 当然循环节也可以为6
141 int x=len2-a[len2];//最小循环节长度 142 if(x==len2) 143 { 144 printf("%d\n",len2);//abcde:5 再加abcde 才可以构成循环 145 } 146 else if (len2%x==0)//aaa :1 已经可以构成循环了 147 { 148 printf("0\n"); 149 } 150 else 151 { 152 printf("%d\n",x-len2%x);// abca : 3 再加bc才可以构成循环 153 } 154 }

求s的最长前缀回文串
ababade :ababa
让p=s的反转
s = s+'#'+p
利用kmp 得到num=c[s.length]
原s[0:num) 为s的最长前缀回文串

在让sp = 原s[num:s.length)
sp的反转+原s--》回文串
即在原s前面加上sp的反转让原s变为回文串
leetcode.cn/problems/shortest-palindrome/description/

 

/**
 * @param {string} s
 * @return {string}
 */
var c  = new Array(500007).fill(0);
 function get(s){
       let  i =0,j=-1;
       c[0]  =-1;
     
       while(Boolean(s[i])==true){
             if(j==-1||s[i]==s[j]) {
                 c[++i]  =++j;
             }else{
                 j  =c[j];
             }
             
       }      
 }
 function revers(s){
     return s.split("").reverse().join("");
 }
var shortestPalindrome = function(s) {
           let tmp  =s;
            let p = revers(s);
            s+='#';
            s+=p;
             get(s);
           
             let num = c[s.length];
            console.log(num)
             let s1 =  revers(tmp.substring(num));

             return s1+tmp;



};

posted on 2018-08-26 22:20  cltt  阅读(254)  评论(0编辑  收藏  举报

导航