1. KMP+Maximum and Minimum Representation
Maximum and Minimum Representation
Maximum and minimum representation is used to solve the problem of string isomorphism. In the time of complexity of $O(n) $, it finds the starting position of the largest (smallest) lexicographic sequence in all isomorphic strings of a string.
Application:
- Give $n $circular strings to determine how many different strings there are: one by one in the largest (smallest) representation, and then add (Set) to de-duplicate
- The representation of maximum (minimum) lexicographic order in all isomorphic strings of a cyclic string: the starting position can be obtained by using the maximum (minimum) representation and the output can be obtained.
- Determine whether two strings are isomorphic: the two strings are represented by the largest (smallest) representation, and then compared character by character
Principle:
Let a string (S\) be the minimal representation of a cyclically isomorphic string of \\(S\\\\\\\\\\\\
The simplest algorithm is to set $i(,\ j (two pointers, ) i (pointing to the position of the smallest representation, J $as the comparison pointer.
Let(i=0), \(j=1), then:
- If (S[i]>S[j]\), then: (i=j), \(j=i+1)
- If (S[i]<S[j]\\), then:(j++\)
- If (S[i]=S[j]\, then set the pointer (k\) from $i $and $j\ (position down comparison until ) S[i]!=S[j], respectively.$
- If \(S[i+k]>S[j+k]\), then:(i=j), \(j=i+1\)
- Otherwise, $j++$
Finally, return $i $
As you can see, the naive algorithm moves too few pointers at $S[i]=S[j] (when, ) I $and encounters something like $bbb... When bbbbbba $is such a complex string, the time complexity may degrade to (O(n^2)\. To solve this problem, we improve the algorithm to get the minimum representation of (O(n)\. The core idea is to maintain both (i) and $J pointers at the same time when $S[i]=S[j]$.
Similarly, let(i=0), (j=1), then:
- If (S[i]>S[j]\), then: (i=j), \(j=i+1)
- If (S[i]<S[j]\\), then:(j++\)
- If $S[i]=S[j](), set the pointer \ k(), and compare it downward from \ i (and \) J $, respectively, until \(S[i]!=S[j]\
- If \(S[i+k]>S[j+k]\, then:(i=i+k)
- Otherwise(j++)
Final return to the small ones of $i $and $j $
1. Minimum Value Representation
int minmumRepresentation(char *str) //Minimum Representation { int len=strlen(str); int i=0; //Point to the smallest position of a string int j=1; //Comparison pointer int k=0; //Moving several times at a time when str[i] and str[j] are equal while(i<len&&j<len&&k<len) { int temp=str[(i+k)%len]-str[(j+k)%len];//Length of comparison value if(temp==0) k++; else { if(temp>0) //Maintenance of i i=i+k+1; else //Maintenance of j j=j+k+1; if(i==j) //Equal-time comparison pointer backward j++; k=0; } } return i<j?i:j; //Return the smaller one in i and j }
2. Maximum Representation
int maxmumRepresentation(char *str) //Maximum Representation { int len=strlen(str); int i=0; //Point to the smallest position of a string int j=1; //Comparison pointer int k=0; //Moving several times at a time when str[i] and str[j] are equal while(i<len&&j<len&&k<len) { int temp=str[(i+k)%len]-str[(j+k)%len];//Length of comparison value if(temp==0) k++; else { if(temp>0) //Maintenance of i j=j+k+1; else //Maintenance of j i=i+k+1; if(i==j) //Equal-time comparison pointer backward j++; k=0; } } return i<j?i:j; //Returns the minimum of both }
Thoughts on HDU-3374 Problem Solving
First, we decide whether it is a cyclic string or not. Then we use the minimum representation and the maximum representation to find the corresponding position. The minimum representation can find a string like a ring, find the beginning of a character, and then the dictionary order of the string is the smallest.
Code:
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #define PI acos(-1.0) #define E 1e-9 #define INF 0x3f3f3f3f #define LL long long const int MOD=10007; const int N=1000000+5; const int dx[]= {-1,1,0,0}; const int dy[]= {0,0,-1,1}; using namespace std; int Next[N]; char str[N]; void getNext(char p[]) { Next[0]=-1; int len=strlen(p); int j=0; int k=-1; while(j<len) { if(k==-1||p[j]==p[k]) { k++; j++; Next[j]=k; } else { k=Next[k]; } } } int minmumRepresentation(char *str) //Minimum Representation { int len=strlen(str); int i=0; int j=1; int k=0; while(i<len&&j<len&&k<len) { int temp=str[(i+k)%len]-str[(j+k)%len]; if(temp==0) k++; else { if(temp>0) i=i+k+1; else j=j+k+1; if(i==j) j++; k=0; } } return i<j?i:j; } int maxmumRepresentation(char *str) //Maximum Representation { int len=strlen(str); int i=0; int j=1; int k=0; while(i<len&&j<len&&k<len) { int temp=str[(i+k)%len]-str[(j+k)%len]; if(temp==0) k++; else { if(temp>0) j=j+k+1; else i=i+k+1; if(i==j) j++; k=0; } } return i<j?i:j; } int main() { while(scanf("%s",str)!=EOF) { getNext(str); int n=strlen(str); int len=n-Next[n]; int num=1;//Number if(n%len==0) num=n/len; int minn=minmumRepresentation(str);//Minimum representation int maxx=maxmumRepresentation(str);//Maximum representation printf("%d %d %d %d\n",minn+1,num,maxx+1,num); } return 0; }