poj3974 Palindrome【回文】【Hash】

Palindrome

Time Limit: 15000MS   Memory Limit: 65536K
Total Submissions: 13157   Accepted: 5028

Description

Andy the smart computer science student was attending an algorithms class when the professor asked the students a simple question, "Can you propose an efficient algorithm to find the length of the largest palindrome in a string?"

A string is said to be a palindrome if it reads the same both forwards and backwards, for example "madam" is a palindrome while "acm" is not.

The students recognized that this is a classical problem but couldn‘t come up with a solution better than iterating over all substrings and checking whether they are palindrome or not, obviously this algorithm is not efficient at all, after a while Andy raised his hand and said "Okay, I‘ve a better algorithm" and before he starts to explain his idea he stopped for a moment and then said "Well, I‘ve an even better algorithm!".

If you think you know Andy‘s final solution then prove it! Given a string of at most 1000000 characters find and print the length of the largest palindrome inside this string.

Input

Your program will be tested on at most 30 test cases, each test case is given as a string of at most 1000000 lowercase characters on a line by itself. The input is terminated by a line that starts with the string "END" (quotes for clarity).

Output

For each test case in the input print the test case number and the length of the largest palindrome.

Sample Input

abcbabcbabcba
abacacbaaaab
END

Sample Output

Case 1: 13
Case 2: 6

Source

Seventh ACM Egyptian National Programming Contest

题意:求一个字符串的最长回文子串

思路:回文串其实就是以一个节点为中间,两端的字符串是相同的。之前的比较字符串相同的Hash函数是以从左到右的顺序,那么这个就再存一个从右到左的字符串的Hash值。对于每一个字符,二分左半子串的长度,分回文串的长度是奇还是偶两种情况。

 1 #include <iostream>
 2 #include <set>
 3 #include <cmath>
 4 #include <stdio.h>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <map>
 8 using namespace std;
 9 typedef long long LL;
10 #define inf 0x7f7f7f7f
11
12 const int maxn = 1e6 + 5;
13 char s[maxn];
14 unsigned long long H[maxn], p[maxn], H_rev[maxn];
15
16 unsigned long long getH(int i, int j)
17 {
18     return H[j] - H[i - 1] * p[j - i + 1];
19 }
20
21 unsigned long long getHrev(int i, int j)
22 {
23     return H_rev[i] - H_rev[j + 1] * p[j - i + 1];
24 }
25
26 int main()
27 {
28     int cas = 1;
29     p[0] = 1;
30     for(int i = 1; i < maxn; i++){
31         p[i] = p[i - 1] * 131;
32     }
33     while(scanf("%s", s + 1)){
34         if(strcmp(s + 1, "END") == 0){
35             break;
36         }
37         int n = strlen(s + 1);
38         H[0] = 0;
39         H_rev[n + 1] = 0;
40         for(int i = 1; i <= n; i++){
41             H[i] = H[i - 1] * 131 + (s[i] - ‘a‘ + 1);
42         }
43         for(int i = n; i >= 1; i--){
44             H_rev[i] = H_rev[i + 1] * 131 + (s[i] - ‘a‘ + 1);
45         }
46
47         int ans = -1;
48         for(int i = 1; i <= n; i++){
49             int ped = min(i - 1, n - i), pst = 1;
50             while(pst < ped){
51                 int pmid = (pst + ped + 1) / 2;
52                 //cout<<pmid<<endl;
53                 if(getH(i - pmid, i - 1) == getHrev(i + 1, i + pmid)){
54                     //
55                     pst = pmid;
56                 }
57                 else{
58                     ped = pmid - 1;
59                 }
60             }
61             //cout<<i<<" "<<pst<<endl;
62             ans = max(ans, 2 * pst + 1);
63             int qed = min(i - 1, n + 1 - i), qst = 1;
64             while(qst < qed){
65                 int qmid = (qst + qed + 1) / 2;
66                 if(getH(i - qmid, i - 1) == getHrev(i, i + qmid - 1)){
67
68                     qst = qmid;
69                 }
70                 else{
71                     qed = qmid - 1;
72                 }
73             }
74             ans = max(ans, 2 * qst);
75
76         }
77
78         printf("Case %d: %d\n", cas++, ans);
79     }
80
81 }

原文地址:https://www.cnblogs.com/wyboooo/p/9817920.html

时间: 2024-08-02 13:50:56

poj3974 Palindrome【回文】【Hash】的相关文章

LeetCode: Palindrome 回文相关题目

LeetCode: Palindrome 回文相关题目汇总 LeetCode: Palindrome Partitioning 解题报告 LeetCode: Palindrome Partitioning II 解题报告 Leetcode:[DP]Longest Palindromic Substring 解题报告 LeetCode: Valid Palindrome 解题报告

leetcode4 Valid Palindrome回文数

Valid Palindrome回文数 [email protected] Question: Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. For example, "A man, a plan, a canal: Panama" is a palindrome. "race a car" i

LeetCode——Valid Palindrome (回文判断)

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. For example, "A man, a plan, a canal: Panama" is a palindrome. "race a car" is not a palindrome. Note: Have you consider that

poj 1159 Palindrome -- 回文串,动态规划

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 59029   Accepted: 20505 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a

hdu 3068最长回文 hash&amp;二分

Time limit  2000 ms Memory limit  32768 kB 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S 两组case之间由空行隔开(该空行不用处理) 字符串长度len <= 110000Output每一行一个整数x,对应一组case,表示该组case的字符串中所包

HDU 1513[Palindrome] 回文串

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 题目大意:给一个字符串,问最少加多少个字母能成为回文串. 关键思想:要解决的是回文子序列问题而不是回文子串.回文子序列怎么求?可以把字符串倒转一下,再求他们的最长公共子序列啊!想一想为什么.求出LCS长度之后,n-LCS才是我们要的答案,因为对于不是回文子序列的其他字符来说,都需要给他们一个对象才能回文(对称).还有一个问题是我们开不了5000*5000的数组,但观察到递推方程是只与两个状态有

台州 OJ 1704 Cheapest Palindrome 回文 区间DP

题目意思:给一个字符串和每个字母删除.插入的代价,求把它变成回文串的最小代价 dp[i][j] 表示 区间 i~j 的子串变成回文串需要的最小代价. 设字符串 ab....cd 如果 a == d,则将其变成回文串的最小代价就是将  b....c 变成回文串 如果 a != d,考虑如下四种情况 在左边插入一个等于 d 的字符变成  dab....cd,则将其变成回文串的代价是将 ab....c 变成回文串的代价,加上插入 d 的代价. 在将左边的 a 删除变成 b....cd,则将其变成回文串

palindrome 回文 /// Manacher算法

判断最长不连续回文 #include <bits/stdc++.h> using namespace std; int main() { char ch[1500]; while(gets(ch)) { int len=strlen(ch),dp[1500],ans=0; for(int i=0;i<len;i++) ch[i]=tolower(ch[i]),dp[i]=1; for(int i=0;i<len;i++) { int cnt=0; for(int j=i-1;j&g

WHU 583 Palindrome ( 回文自动机 &amp;&amp; 本质不同的回文串的个数 )

题目链接 题意 : 给你一个串.要你将其划分成两个串.使得左边的串的本质不同回文子串的个数是右边串的两倍.对于每一个这样子的划分.其对答案的贡献就是左边串的长度.现在要你找出所有这样子的划分.并将贡献乘起来.答案 mod 1e9+7 分析 : 从左到右跑一边回文自动机.对于每个前缀 能够得出其有多少个本质不同的回文子串 本质不同的回文子串的个数实际上就是自动机节点数 - 2 那么跑一遍前缀之后我们能得到所有可作为左边部分串的本质不同回文子串的个数 因为是回文串.所以我们倒着跑一遍.就同样能得到作

使用递归方式判断某个字串是否是回文( palindrome )

"回文"是指正着读.反着读都一样的句子.比如"我是谁是我" 使用递归算法检测回文的算法描述如下: A single or zero-character string is a palindrome. Any other string is a palindrome if the first and last characters are the same, and the string that remains, excepting those characters