zcmu 1550 (die kleinste Darstellung einer Zeichenfolge)

Titellink: https://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1550

Thema

Geben Sie eine Zeichenfolge s, sie kann sich nach links drehen, und bitten Sie die Zeichenfolge, die lexikografisch am wenigsten lexikografisch zu sein, nachdem Sie sie mehrmals nach links verschoben haben.

Zyklus links, zum Beispiel s ist (adac), dann kann die Linksverschiebung adac, daca, acad, cada sein. Die kleinste lexikografische Reihenfolge ist hier acad, daher muss sie dreimal nach links verschoben werden.

Ideen

O (n ^ 2) tritt eine Zeitüberschreitung auf, hier ist ein O (n) -Ansatz

i, j sind zwei Zeiger, die die Position des ersten Buchstabens der beiden Zeichenfolgen angeben. k stellt die längste gemeinsame Präfixlänge von zwei Zeichenfolgen dar. Da die beiden Arrays in lexikografischer Reihenfolge verglichen werden müssen, können i und j nicht gleich sein, und i wird auf 0 initialisiert, j wird auf 1 initialisiert und k wird auf 0 initialisiert

Wenn s [i + k] == s [j + k] ist, wird die Länge von k als gemeinsames Präfix um 1 erhöht.

Wenn s [i + k]> s [j + k] ist, springe ich k + 1, um die Position von i + k + 1 zu erreichen

Wenn s [i + k] <s [j + k] ist, springt j k + 1, um die Position von j + k + 1 zu erreichen. Warum?

Was wir beachten sollten, ist, dass es als Zeichenfolge mit der kleinsten lexikografischen Reihenfolge Zeichenfolgen mit derselben Länge geben muss, die von s [i + 1 bis j-1] beginnen und nicht kleiner sind als diejenigen, die von s [i] beginnen. , sonst bin ich vor langer Zeit nach hinten gesprungen, wenn s [i + k]> s [j + k], dann zeigt es an, dass der Index ab j eine kleinere lexikographische Reihenfolge der Länge k hat

Dann muss ich angepasst werden. Da die Länge der Zeichenfolge ab j k ist, müssen die k-Positionen nach dem Start von i nicht ausgeführt werden, da sie nicht kleiner sind als die aktuelle Zeichenfolge ab j, also i musste k + 1 Positionen springen. Wenn s [i + k] <s [j + k] ist, gilt das Gleiche.

Um sicherzustellen, dass i und j nicht gleich sein können, müssen wir beurteilen. Wenn sie gleich sind, lassen wir j ++, und schließlich muss die lexikografische Reihenfolge der Zeichenfolge der Länge n ab i die kleinste sein.

AC-Code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 3e5 + 5;
char s[maxn];
int cal(int n){
    int i = 0, j = 1, k = 0;
    while(i < n && j < n && k < n) {
        int c1 = (i + k) % n, c2 = (j + k) % n;
        if(s[c1] == s[c2]) k ++;
        else {
            if(s[c1] < s[c2]) j += k + 1;
            else i += k + 1;
            if(i == j) j ++;
            k = 0;
        }
    }
    return i;
}
int main(){
    int t; scanf("%d",&t);
    while(t --){
        scanf("%s", s);
        printf("%d\n", cal(strlen(s)));
    }
    return 0;
}

Weitere Fragen

Eine andere ähnliche Frage  P1368 [Vorlage] Minimale Notation

Man kann sagen, dass die Methode genau dieselbe ist, aber sie gibt die Zeichenfolge mit der kleinsten lexikografischen Reihenfolge aus

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 3e5 + 5;
int s[maxn];
int cal(int n){
    int i = 0, j = 1, k = 0;
    while(i < n && j < n && k < n){
        int d1 = (i + k) % n, d2 = (j + k) % n;
        if(s[d1] == s[d2]) k ++;
        else{
            if(s[d1] > s[d2]) i += k + 1;
            else j += k + 1;
            if(i == j) j ++;
            k = 0;
        }
    }
    return i;
}
int main(){
    int n; scanf("%d",&n);
    for(int i = 0; i < n; i ++) {
        scanf("%d",&s[i]);
    }
    int ans = cal(n);
    for(int i = 0; i < n; i ++) {
        if(i) printf(" ");
        printf("%d", s[(i + ans) % n]);
    }
    puts("");

    return 0;
}

 

Ich denke du magst

Origin blog.csdn.net/weixin_43911947/article/details/112674690
Empfohlen
Rangfolge