• [POJ3974]Palindrome(后缀数组 || manacher)


    传送门

    求一个串的最长回文子串的长度

    1.后缀数组

    把这个串反转后接到原串的后面,中间连一个没有出现过的字符。

    然后求这个新字符串的某两个后缀的公共前缀的最大值即可。

    ——代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #define N 2000010
     5 #define max(x, y) ((x) > (y) ? (x) : (y))
     6 
     7 int n, m, len, ans;
     8 int buc[N], x[N], y[N], sa[N], rank[N], height[N];
     9 char s[N];
    10 
    11 inline void build_sa()
    12 {
    13     int i, k, p;
    14     for(i = 0; i < m; i++) buc[i] = 0;
    15     for(i = 0; i < len; i++) buc[x[i] = s[i]]++;
    16     for(i = 1; i < m; i++) buc[i] += buc[i - 1];
    17     for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i;
    18     for(k = 1; k <= len; k <<= 1)
    19     {
    20         p = 0;
    21         for(i = len - 1; i >= len - k; i--) y[p++] = i;
    22         for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
    23         for(i = 0; i < m; i++) buc[i] = 0;
    24         for(i = 0; i < len; i++) buc[x[y[i]]]++;
    25         for(i = 1; i < m; i++) buc[i] += buc[i - 1];
    26         for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];
    27         std::swap(x, y);
    28         p = 1, x[sa[0]] = 0;
    29         for(i = 1; i < len; i++)
    30             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
    31         if(p >= len) break;
    32         m = p;
    33     }
    34 }
    35 
    36 inline void build_height()
    37 {
    38     int i, j, k = 0;
    39     for(i = 0; i < len; i++) rank[sa[i]] = i;
    40     for(i = 0; i < len; i++)
    41     {
    42         if(!rank[i]) continue;
    43         if(k) k--;
    44         j = sa[rank[i] - 1];
    45         while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++;
    46         height[rank[i]] = k;
    47     }
    48 }
    49 
    50 int main()
    51 {
    52     int i, k, tot = 0;
    53     while(scanf("%s", s))
    54     {
    55         if(s[0] == 'E' && s[1] == 'N' && s[2] == 'D') break;
    56         tot++;
    57         ans = 0;
    58         m = 256;
    59         k = strlen(s);
    60         s[k] = '#';
    61         for(i = 0; i < k; i++) s[k + i + 1] = s[k - i - 1];
    62         len = k << 1 | 1;
    63         build_sa();
    64         build_height();
    65         for(i = 1; i < len; i++)
    66             if((sa[i - 1] < k && sa[i] > k) || (sa[i - 1] > k && sa[i] < k))
    67                 ans = max(ans, height[i]);
    68         printf("Case %d: %d
    ", tot, ans);
    69     }
    70     return 0;
    71 }
    View Code

    2.manacher

    #include <cstdio>
    #include <cstring>
    #define N 2100000
    #define min(x, y) ((x) < (y) ? (x) : (y))
    #define max(x, y) ((x) > (y) ? (x) : (y))
    
    int p[N];
    char s[N];
    int n, pos, maxright, ans;
    
    int main()
    {
    	int i, cnt = 0;;
    	while(scanf("%s", s + 1) && s[1] != 'E')
    	{
    		cnt++;
    		n = strlen(s + 1);
    		s[0] = '$', s[n * 2 + 1] = '#';
    		for(i = n; i >= 1; i--)
    			s[i * 2] = s[i], s[i * 2 - 1] = '#';
    		n *= 2;
    		pos = 1, maxright = 0, ans = 0;
    		for(i = 1; i <= n; i++)
    		{
    			p[i] = 1;
    			if(i <= maxright)
    				p[i] = min(p[pos * 2 - i], maxright - i + 1);
    			while(s[i - p[i]] == s[i + p[i]]) p[i]++;
    			if(maxright < i + p[i] - 1)
    			{
    				pos = i;
    				maxright = i + p[i] - 1;
    			}
    			ans = max(ans, p[i] - 1);
    		}
    		printf("Case %d: %d
    ", cnt, ans);
    	}
    	return 0;
    } 
    

      

  • 相关阅读:
    [反汇编练习] 160个CrackMe之002
    [反汇编练习]160个CrackMe之001
    Leap Motion 开发笔记
    HTMLayout界面CSSS样式解析笔记
    DbgPrint输出格式 Unicodestring
    WinDbg调试命令汇总
    WDF模型驱动程序开发
    [Sciter系列] MFC下的Sciter–5.Sciter中GUI线程研究
    剑指offer第二版-4.二维数组中的查找
    剑指offer第二版-3.数组中重复的数
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6991487.html
Copyright © 2020-2023  润新知