最小表示法字符串
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小表示法字符串相关的知识,希望对你有一定的参考价值。
最小表示法
1️⃣ 简介
最小表示法就是找 字符串S的循环同构串中字典序最小的一个 的算法,属于是字符串算法。
循环同构串:
例子:字符串
S
:bcad
, 则S
的循环同构串为bcad
,cadb
,adbc
,dbca
故循环同构串可以有多个,它是原字符串循环移位产生的字符串
2️⃣ 实现方法
最小表示法其实就是找到位置i
,从这个位置输出S
,使得到的同构串字典序最小。
暴力解法
关键是如何找:需要先知道暴力的简单方法,然后再对暴力做一些优化即可。
每次比较的是 i i i和 j j j开始的循环同构,把当前比较的位置记为 k k k.
int k = 0, i = 0, j = 1;
while (k < n && i < n && j < n)
if (a[(i + k) % n] == a[(j + k) % n])
++k;
else
if (sec[(i + k) % n] > sec[(j + k) % n]) ++i;
else ++j;
k = 0;
if (i == j) i++;
i = min(i, j);
优化后的算法(最小表示法)
优化后的代码:
int i = 0, j = 1, k = 0;
while(i < n and j < n and k < n)
if(a[(i + k) % n] == a[(j + k) % n])
k++;
else
a[(i + k) % n] > a[(j + k) % n] ? i = i + k + 1 : j = j + k + 1;
if(i == j)
i++;
k = 0;
i = min(i, j);
模板题目
题目链接
https://www.luogu.com.cn/problem/P1368
找数组所有的循环同构中最小的字典序的数组
#include<bits/stdc++.h>
using namespace std;
using ll = long long ;
void solve()
int n;
cin >> n;
vector<int> a(n + 1);
for(int i = 0; i < n; i++)
cin >> a[i];
int i = 0, j = 1, k = 0;
while(i < n and j < n and k < n)
if(a[(i + k) % n] == a[(j + k) % n])
k++;
else
a[(i + k) % n] > a[(j + k) % n] ? i = i + k + 1 : j = j + k + 1;
if(i == j)
i++;
k = 0;
i = min(i, j);
for(int x = 0; x < n; x++)
cout << a[(x + i) % n] << " \\n"[x == n - 1];
int main()
ios::sync_with_stdio(false);
cin.tie(0);
int t;
// cin >> t;
t = 1;
while(t--)
solve();
return 0;
以上是关于最小表示法字符串的主要内容,如果未能解决你的问题,请参考以下文章