最小表示法的推广 -》 最大表示
分别求 正序跟逆序的,但是由于这道题要起点最小,那么逆序的时候不能找到第一个就返回。要继续往后找
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <map>
using namespace std;
#define MAXN 20010
char str1[MAXN*2], str2[MAXN*2];
char ans1[MAXN], ans2[MAXN];
int getminstr(char str[], int len)
{
int i = 0, j = 1, k = 0;
while( i < len && j < len)
{
k = 0;
while(str[i + k] == str[j + k] && k < len) k++;
if(k == len) return min(i, j);
if(str[i + k] < str[j + k])
{
if(i + k + 1 <= j)
i = j + 1;
else
i = i + k + 1;
}
else
{
if(j + k + 1 <= i)
j = i + 1;
else
j = j + k + 1;
}
}
return min(i, j);
}
int getmaxstr(char x[], int n)
{
int i = 0, j = 1, k;
while(i < n && j < n)
{
k = 0;
while(x[i + k] == x[j + k] && k < n)
k++;
if (k == n)
{
i = max(i, j);
j = i + 1;
}
else
{
if (x[i + k] < x[j + k])
if (i + k + 1 > j)
i = i + k + 1;
else
i = j + 1;
else {if (j + k + 1 > i)
j = j + k + 1;
else
j = i + 1;
}
}
}
if(j >= n)
return i;
return j;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int l;
scanf("%d",&l);
scanf("%s",&str1);
for( int i = 0; i < l; i++)
str2[2*l - 1 - i] = str1[i + l] = str2[l - 1 - i] = str1[i];
str1[2*l] += '\0';
str2[2*l] += '\0';
int a = getminstr(str1, l);
int b = getmaxstr(str2, l);
// printf("%s -- %d\n",str1, a);
//printf("%s -- %d\n",str2, b);
for( int i = 0; i < l; i++)
{
ans1[i] = str1[a + i];
ans2[i] = str2[b + i];
}
ans1[l] = '\0';
ans2[l] = '\0';
if(strcmp(ans1, ans2) > 0)
printf("%d 0\n",a + 1);
else if(strcmp(ans1, ans2) < 0)
printf("%d 1\n",l - b );
else
{
if(l - b < a + 1)
printf("%d 1\n",l - b);
else
printf("%d 0\n",a + 1);
}
}
return 0;
}
http://www.cnblogs.com/julyed/p/4812996.html
看到有打牛说,当求逆序出现第一个最大表示的时候,其实这个时候字符串有循环节的正好是 j-i+1 那么最有一次出现第i个字符的位置是可以推算出来的,