↓ Skip to main content
  1. Posts/

poj 3294 Girls' research (manacher,回文串)

·1257 words·3 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

poj 3294 题意:先做个简单替换,然后求替换后的字符串的最长回文串,以及这个最长回文串的开始和结束位置。 思路:manacher。需要注意的是,返回下标的时候如果字符串长度为偶数,那么中间是没有字符的,需要特判一下(我的做法是 left+(ans%2==0))。

代码实现
  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年04月18日 星期一 19时40分06秒
  4File Name :code/hdu/3294.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=4E5+7;
 34char st[N],st2[N];
 35int p[N];
 36char ch;
 37
 38void manacher(char *s)
 39{
 40    int len = strlen(s);
 41
 42    for ( int i = len ;  i>= 0 ; i--)
 43    {
 44    s[i*2+2] = s[i];
 45    s[i*2+1] = '#';
 46    }
 47
 48    int id = 0 ;
 49    int maxlen = 0 ;
 50    int center = 0 ;
 51    s[0]='%';
 52    for ( int i = 2 ; i < 2*len+1 ; i++)
 53    {
 54    if (id+p[id]>i) p[i] = min(p[2*id-i],p[id]+id-i);
 55    else p[i] = 1;
 56
 57    while (s[p[i]+i]==s[i-p[i]]) p[i]++;
 58
 59    if (id+p[id]<i+p[i]) id = i;
 60    if (p[i]>maxlen)
 61    {
 62        maxlen = p[i];
 63        center = i;
 64    }
 65    }
 66    int ans = (maxlen-1);
 67   // cout<<"ans:"<<ans<<" center:"<<center<<endl;
 68    if (ans<2)
 69    {
 70    puts("No solution!");
 71    }
 72    else
 73    {
 74    int left = center/2-1-ans/2+(ans%2==0);
 75    int right = center/2-1+ans/2;
 76    printf("%d %d\n",left,right);
 77    for ( int  i = left ; i <= right ; i++) printf("%c",st2[i]);
 78    printf("\n");
 79    }
 80
 81}
 82int main()
 83{
 84    #ifndef  ONLINE_JUDGE
 85    freopen("code/in.txt","r",stdin);
 86  #endif
 87
 88    while (scanf("%c %s\n",&ch,st)!=EOF)
 89    {
 90        int k = ch-'a';
 91        int len = strlen(st);
 92        for ( int i = 0 ; i < len ; i++)
 93        {
 94        int tmp = (st[i]-'a'-k+26);
 95        st[i] = char(tmp+'a');
 96        st2[i] = st[i];
 97        }
 98    //    cout<<"st:"<<st<<endl;
 99        manacher(st);
100    }
101
102  #ifndef ONLINE_JUDGE
103  fclose(stdin);
104  #endif
105    return 0;
106}
107
108
109
110
111
112
113
114
115#include <bits/stdc++.h>
116#define fst first
117#define sec second
118#define lson l,m,rt<<1
119#define rson m+1,r,rt<<1|1
120#define ms(a,x) memset(a,x,sizeof(a))
121typedef long long LL;
122#define pi pair < int ,int >
123#define MP make_pair
124
125using namespace std;
126const double eps = 1E-8;
127const int dx4[4]={1,0,0,-1};
128const int dy4[4]={0,-1,1,0};
129const int inf = 0x3f3f3f3f;
130const int N=5E5+79;
131int t[2*N];
132char st[N];
133int p[2*N];  //p[i]为以第i个位置的字符为中心的回文串的半径长,默认为1.
134vector<int>vec[N];
135int a[2*N];
136char Ma[2*N];
137int Mp[2*N];
138int Manacher( char *s)
139{
140    int len = strlen(s);
141    int id = 0; //id表示之前位置的能延伸到最远位置的字符串的中心位置。
142    int maxlen = 0 ;  //maxlen是为了更新答案而用。。。就是记录了一个最大值。。。
143    int mx = 0 ;//mx为当前位置之前的回文串能延伸到的最远位置 即:max(p[j]+j) (j<i)
144                //如果知道之前能延伸到最远位置的字符串的中心位置的下标为id,那么就是p[id]+id;
145    for ( int i = len ; i >= 0 ; i--)  //插入'#'是为了将字符串长度奇偶性不同的统一考虑。
146    {
147        Ma[i+i+2] = s[i];
148        Ma[i+i+1] = '#';
149    }
150    Ma[0]='*'; //s[0] ='*'以及用字符数组最后默认的s[len+len+2]='\0'是为了下面while 循环的时候不溢出。。
151                //两边的字符一定要不一样。。用string的话记得两边都加字符。。。
152    for ( int i = 2 ; i < 2*len+1 ; i++)
153    {
154        if (Mp[id]+id>i) Mp[i] = min(Mp[2*id-i],Mp[id]+id-i);
155        else Mp[i] = 1;
156        while (Ma[i-Mp[i]]==Ma[i+Mp[i]]) Mp[i]++;
157        if (id+Mp[id]<i+Mp[i]) id = i;
158        if (maxlen<Mp[i]) maxlen = p[i];
159    }
160    return 2*len+2;
161    //这道题是问最长回文串的长度。。。如果是问回文串是什么的话。。。根据id和maxlen也可以构造出来。。。
162}
163
164int lowbit( int x) { return x&(-x);}
165void update ( int x,int delta)
166{
167    for ( int i = x; i < 2*N ; i+=lowbit(i))
168    t[i]+=delta;
169}
170int Sum( int x)
171{
172    int res = 0 ;
173    for ( int i = x ; i >= 1 ; i-=lowbit(i))
174    res = res + t[i];
175    return res;
176}
177int main()
178{
179        #ifndef  ONLINE_JUDGE
180       freopen("./in.txt","r",stdin);
181  #endif
182    int T;
183    cin>>T;
184    while (T--)
185    {
186        ms(t,0);
187        for ( int i = 0 ; i < N ; i++) vec[i].clear();
188        scanf("%s",st);
189        int n = strlen(st);
190        int len = Manacher(st);
191        int k = 1;
192        for ( int i = 2 ; i < len ; i+=2)
193        {
194        a[k] = Mp[i]/2-1;
195
196        printf("k:%d a[k]:%d p[i]:%d\n",k,a[k],Mp[i]);
197        vec[k-a[k]].push_back(k);
198        k++;
199        }
200        LL ans = 0 ;
201        for ( int i = 1 ; i <= n  ; i++)
202        {
203//      cout<<"a[i]:"<<a[i]<<endl;
204        for ( int j = 0 ; j < vec[i].size() ; j++)
205            update(vec[i][j],1);
206        ans += Sum(min(i+a[i],n)) -Sum(i);
207        }
208//      cout<<Sum(2*N)<<endl;
209        cout<<ans<<endl;
210    }
211  #ifndef ONLINE_JUDGE
212  fclose(stdin);
213  #endif
214    return 0;
215}

Related

poj 3974 Palindrome (最长回文字串,manacher裸题)

·297 words·1 min
poj3974 题意:求最大长度的回文字串。 思路:manacher裸题,用来练习算法。 代码实现 1/* *********************************************** 2Author :111qqz 3Created Time :2016年04月18日 星期一 16时32分25秒 4File Name :code/poj/3974.cpp 5************************************************ */ 6 7#include <cstdio> 8#include <cstring> 9#include <iostream> 10#include <algorithm> 11#include <vector> 12#include <queue> 13#include <set> 14#include <map> 15#include <string> 16#include <cmath> 17#include <cstdlib> 18#include <ctime> 19#define fst first 20#define sec second 21#define lson l,m,rt<<1 22#define rson m+1,r,rt<<1|1 23#define ms(a,x) memset(a,x,sizeof(a)) 24typedef long long LL; 25#define pi pair < int ,int > 26#define MP make_pair 27 28using namespace std; 29const double eps = 1E-8; 30const int dx4[4]={1,0,0,-1}; 31const int dy4[4]={0,-1,1,0}; 32const int inf = 0x3f3f3f3f; 33const int N=2E6+7; 34char st[2*N]; 35int p[2*N]; 36 37int manacher(char *s) 38{ 39 int len = strlen(s); 40 for ( int i = len ; i >= 0 ; i-- ) 41 { 42 s[i+i+2]=s[i]; 43 s[i+i+1]='#'; 44 } 45 s[0]='$'; 46 47 int id = 0 ; 48 int maxlen = 0 ; 49 50 for ( int i = 2 ; i < 2*len+1 ; i++) 51 { 52 if (id+p[id]>i) p[i] = min(p[2*id-i],id+p[id]-i); 53 else p[i] = 1; 54 55 while (s[i+p[i]]==s[i-p[i]]) p[i]++; 56 if (id+p[id]<i+p[i]) id = i; 57 if (p[i]>maxlen) maxlen = p[i]; 58 } 59 return maxlen-1; 60} 61int main() 62{ 63 #ifndef ONLINE_JUDGE 64 freopen("code/in.txt","r",stdin); 65 #endif 66 int cas = 0 ; 67 while (scanf("%s",st)!=EOF) 68 { 69 if (st[0]=='E'&&st[1]=='N'&&st[2]=='D') break; 70 printf("Case %d: %d\n",++cas,manacher(st)); 71 72 } 73 74 #ifndef ONLINE_JUDGE 75 fclose(stdin); 76 #endif 77 return 0; 78}

BZOJ 1657: [Usaco2006 Mar]Mooo 奶牛的歌声 (单调栈)

·1062 words·3 mins
1657: [Usaco2006 Mar]Mooo 奶牛的歌声 # Time Limit: 5 Sec Memory Limit: 64 MB Submit: 634 Solved: 447 [Submit][Status][Discuss] Description # Farmer John’s N (1 <= N <= 50,000) cows are standing in a very straight row and mooing. Each cow has a unique height h in the range 1..2,000,000,000 nanometers (FJ really is a stickler for precision). Each cow moos at some volume v in the range 1..10,000. This “moo” travels across the row of cows in both directions (except for the end cows, obviously). Curiously, it is heard only by the closest cow in each direction whose height is strictly larger than that of the mooing cow (so each moo will be heard by 0, 1 or 2 other cows, depending on not whether or taller cows exist to the mooing cow’s right or left). The total moo volume heard by given cow is the sum of all the moo volumes v for all cows whose mooing reaches the cow. Since some (presumably taller) cows might be subjected to a very large moo volume, FJ wants to buy earmuffs for the cow whose hearing is most threatened. Please compute the loudest moo volume heard by any cow.

BZOJ 1656: [Usaco2006 Jan] The Grove 树木(神奇的bfs之射线法)

·1177 words·3 mins
1656: [Usaco2006 Jan] The Grove 树木 # Time Limit: 5 Sec Memory Limit: 64 MB Submit: 143 Solved: 88 [Submit][Status][Discuss] Description # The pasture contains a small, contiguous grove of trees that has no ‘holes’ in the middle of the it. Bessie wonders: how far is it to walk around that grove and get back to my starting position? She’s just sure there is a way to do it by going from her start location to successive locations by walking horizontally, vertically, or diagonally and counting each move as a single step. Just looking at it, she doesn’t think you could pass ’through’ the grove on a tricky diagonal. Your job is to calculate the minimum number of steps she must take. Happily, Bessie lives on a simple world where the pasture is represented by a grid with R rows and C columns (1 <= R <= 50, 1 <= C <= 50). Here’s a typical example where ‘.’ is pasture (which Bessie may traverse), ‘X’ is the grove of trees, ‘’ represents Bessie’s start and end position, and ‘+’ marks one shortest path she can walk to circumnavigate the grove (i.e., the answer): …+… ..+X+.. .+XXX+. ..+XXX+ ..+X..+ …+++ The path shown is not the only possible shortest path; Bessie might have taken a diagonal step from her start position and achieved a similar length solution. Bessie is happy that she’s starting ‘outside’ the grove instead of in a sort of ‘harbor’ that could complicate finding the best path.