查找字符串中按字典顺序排列的最大旋转
Finding the lexicographically largest rotations in the string
我需要从给定的输入字符串中找到词法上最大的字符串。因此,如果输入是
enjoy
o/p应该是
yenjo
我尝试的代码是。。。。
int n;
cout<<"Enter the number of strings";
cin>>n;
int len[n];
char str[n][1000];
for(int i=0;i<n;i++)
{
cin>>str[i];
len[i]=strlen(str[i]);
}
int num,pos[n];
for(int i=0;i<n;i++)
{
pos[i]=0;
num=int(str[i][0]);
for(int j=1;j<len[i];j++)
{
if(int(str[i][j])>num)
{
num=int(str[i][j]);
pos[i]=j;
}
}
}
int i,j,k;
char temp[1];
for(i=0;i<n;i++)
{
for(j=0;j<pos[i];j++)
{
temp[0]=str[i][0];
for(k=0;k<len[i];k++)
{
str[i][k]=str[i][k+1];
}
strcat(str[i],temp);
str[i][len[i]]=' ';
}
cout<<str[i]<<"n";
}
return 0;
}
但是,这个代码只对最大的数字进行编码,而对旁边的数字不进行编码,因此对i/p 失败
blowhowler
o/p应该是wlerblowho
,但我得到的o/p是whowlerblo
。
如何跟踪每一个包含最大字符的元素,以便获得正确的输出?
为了在平均情况下获得良好的性能(实际上是O(N)),但在最坏的情况下仍然是O^2(并且总是正确的),您可以跟踪各种可能性,并在进行过程中不断消除它们。基本上是这样的。
struct PermSum
{
int sum;
int perm;
}
LinkedList<PermSum> L;
for(int i = 0; i != input.size(); ++i) L.append(PermSum{0,i});
int depth = 0;
int max = 0;
const int length = input.size()
while(L.size() > 1 && depth < length)
{
for(l in L)
{
l.sum += input[(l.perm + depth) % length]
if (l.sum > max) max = l.sum
}
for(l in L)
{
if (l.sum < max) L.delete(l)
}
depth ++;
}
if (L.size() == 1)
return L.front().perm
else
return -1
我在c++代码的某些部分有点懒,但我相信你可以在l中找到l。关键行是循环的第一行。其思想是,它在l.perm-th排列的字母深度处添加词典学值。通过这种方式,它更新了所有的可能性,同时跟踪最佳可能性的水平。然后你做第二次传球,删除任何可能达不到最佳水平的可能性。值得注意的是,我编码的方式可能与循环排列的标准约定相反。也就是说,我的程序中的perm字段表示你循环移位的左边有多少个点,而通常正数是循环右移。你可以在某个地方用减号来解决这个问题。
至于运行时间分析,它与Quickselect基本上是相同的参数。每次while循环迭代所花费的时间与L的长度成比例。第一次迭代,L的长度总是=N(其中N是字符串的长度,与代码中的可变长度相同)。下一轮,我们通常只期望1/26的数据通过,下一轮是1/26。。。所以我们有N(1+1/26+2/26^2…),它是O(N)。
这个问题可以在O(n log n)时间内解决,方法是先将字符串附加到它本身,然后用它构建后缀数组。找到相应的条目,就可以得到你想要的结果。执行作为练习。
您可以:1.生成旋转2.将所有旋转放在map中<>3.找到地图的最后一个元素。以下是C++中的实现。
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
int main() {
// your code goes here
string str;int len,i=0,j=0,k=0;char temp;
cin>>str;
len = str.length();
map<string,int>m;
while(i<len)
{
temp = str[0];
while(j<len-1)
{
str[j] = str[j+1];
j++;
}
str[j] = temp;
m[str] = k;
k++;
i++;j=0;
}
str = m.rbegin()->first;
cout<<str;
return 0;
}
//Here the index with greater value is selected,
//if the same char occurs again the next characters
// of prev and curr characters is checked:-Prev=maxIndex,curr=i
#include<bits/stdc++.h>
using namespace std;
int getIndex(char *str){
int max=INT_MIN,maxIndex;
int n=strlen(str);
int j,p;
for(int i=0;i<n;i++)
{
if(str[i]>max)
{
max=str[i];
maxIndex=i;
}
else if(str[i]==max)
{
j=maxIndex+1;
p=(i+1)%n;
while(j<n && p<n && str[j]==str[p]){
j++;
p=(p+1)%n;
}
maxIndex=str[p]>str[j]?i:maxIndex;
}
}
return maxIndex;
}
int main(void)
{
char str[4000008];
scanf("%s",str);
int i=getIndex(str);
for(int j=i;j<strlen(str);j++)
cout<<str[j];
for(int j=0;j<i;j++)
cout<<str[j];
}
经过校正后,您的算法归结为:
- 将当前最佳旋转设置为标识(旋转字符串的开头为当前索引0)
- 对于每个可能的旋转(所有其他起始索引):
- 与下面类似
wrapcmp
的当前最佳旋转进行比较 - 如果我们有更好的候选人,请设置当前的最佳轮换
- 与下面类似
时间复杂度:O(n*n)
空间复杂性:原位
// Function to do ordinal-comparison on two rotations of a buffer
// buffer: The buffer containing the string
// n: The buffers size (string-length)
// a: Index where the first buffer starts pre-rotation
// b: Index where the second buffer starts pre-rotation
int wrapcmp(const void* buffer, size_t n, size_t a, size_t b) {
auto x = (const unsigned char*)buffer;
auto m = n - std::max(a, b);
int ret = memcmp(x+a, x+b, m);
if(ret) return ret;
auto left = n - m;
a = (a + m) % n;
b = (b + m) % n;
m = left - std::max(a, b);
ret = memcmp(x+a, x+b, m);
if(ret) return ret;
a = (a + m) % n;
b = (b + m) % n;
return memcmp(x+a, x+b, left - m);
}
用于coliru:http://coliru.stacked-crooked.com/a/4b138a6394483447
把它放在普通算法中,留给读者练习。
这太诱人了,所以我不妨发布我的努力。不确定它如何评价效率魔法。据我测试,它似乎有效:
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
std::string max_rot(const std::string& s)
{
std::string tmp;
std::string max;
std::string::const_iterator m = std::max_element(s.begin(), s.end());
if(m != s.end())
for(char c = *m; (m = std::find(m, s.end(), c)) != s.end(); ++m)
if(max < tmp.assign(m, s.end()).append(s.begin(), m))
max = tmp;
return max;
}
int main()
{
size_t times = 0;
std::string text;
do { std::cout << "nHow many words? : "; }
while(std::getline(std::cin, text) && !(std::istringstream(text) >> times));
std::vector<std::string> words;
while(times-- && (std::cin >> text))
words.push_back(text);
for(const auto& s: words)
std::cout << max_rot(s) << 'n';
}
作为解释。它会找到字符串中最高的字符值,并旋转字符串以使该字符位于第一位。如果然后在字符串的剩余部分中查找重复的最高字符,以跟踪最高尝试。也许还有优化的空间。
此挑战用于活动比赛,我要求在9月18日至9月9日下午IST之前不提供答案。因为代码是可见的,我们可能不得不禁止用户参与我们的任何比赛。
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么不;名字在地图上是按顺序排列的吗
- 与互斥锁相比,旋转锁可以保证上下文切换
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 绘制旋转的三角形
- 旋转模型矩阵时的形状失真
- 四边形的 2D 旋转
- 垂直方向的 Gtk3+ 旋转按钮 (c/c++)
- 发布旋转矩阵(openGL/glm)
- 找到具有最多子串栅栏的字符串排列
- 顺时针迭代旋转 3 位数字
- 重新排列单线以形成闭合多边形?
- 形状对象的旋转和缩放不正确C++
- 如何在 OpenSceneGraph 中缩放/旋转/移动资产
- 如何有效地计算将单位立方体映射到自身的反射和旋转?
- 子轴围绕父轴而不是他自己的轴旋转
- 将使用太多的纹理插值器 - 带旋转的着色器
- 查找字符串中按字典顺序排列的最大旋转
- 生成除循环旋转之外的所有排列