How many最大最小表示法重组字符串统一最小表示

题目
Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tell me
How many kinds of necklaces total have.(if two necklaces can equal by rotating ,we say the two necklaces are some).
For example 0110 express a necklace, you can rotate it. 0110 -> 1100 -> 1001 -> 0011->0110.
Input
The input contains multiple test cases.
Each test case include: first one integers n. (2<=n<=10000)
Next n lines follow. Each line has a equal length character string. (string only include ‘0’,‘1’).
Output
For each test case output a integer , how many different necklaces.
Sample Input
4
0110
1100
1001
0011
4
1010
0101
1000
0001
Sample Output
1
2
这一道题大致思路就是 对于一个01串 可以每次将最前面的一个字符移动到后面 然后移动后第一个串的所有同构的串和第二个所有同构的串一一相同 就说这两个串是一种 我们可以规定一个标准 字典序最小的表示的串 相同就记为一种串 。。

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
//char a[2000005];
set<string> str;
//int  f[2000005],exf[205];
//void fc(char *p,int l)
//{
//    int i=0;
//    int j=-1;
//    f[0]=-1;
//    while(i<l)
//    {
//        while(j==-1||p[i]==p[j])
//        {
//            f[++i]=++j;
//        }
//        if(p[i]!=p[j])
//        {
//            j=f[j];
//        }
//    }
//
//
//}
int getminmax(int flag,string p)
{
   // char x[2000005];
    int  lp= p.length() ;
    int i=0,j=1,k=0;
    while(i<lp&&j<lp&&k<lp)
    {

        int t=p[(j+k)%lp]-p[(i+k)%lp];
        if(t==0)
        {
            k++;

        }
        else
        {
            if(flag)
            {
                if(t>0)
                {
                    j+=k+1;
                }
                else
                {
                    i+=k+1;
                }
            }
            else
            {
                if(t>0)
                {
                    i+=k+1;

                }
                else
                {
                    j+=k+1;
                }

            }
            if(j==i)
            {
                j++;
            }
            k=0;
        }
    }
    return min(i,j);
}

//bool kmp(char *p,int l1,char *q,int l2 )
//{
//
//    int j=0;
//    int i=0;
//    while(i<l2)
//    {
//      if(j==-1||q[i]==p[j])
//        {
//           ++i;
//           ++j;
//        }
//        else
//        {
//            j=f[j];
//        }
//        if(j==l1)
//        {
//            return true;
//        }
//    }
//    return false;

   int j=-1;//会wa原因是我不知道求大佬评论区解答一下哇
 for(int w=0;w<l2;w++)
 {
     if(q[w]==p[j+1])
     {
         j++;
     }
     while(j>-1&&q[w]!=p[j+1])
     {
         j=f[j];
     }
     if(j+1==l1)
     {
        return true;
     }
 }
   return false;
//
//}
string  group(string pp)
{
    int k=getminmax(1,pp);
    int len=pp.length();
    string st="";
    for(int i=k+1;i<=len+k;i++)
        st+=pp[i%len];
    return st;
}
int main()
{

    int n;
    while(scanf("%d",&n)!=EOF)
    {
        str.clear();
        while(n--)
        {
            string ss;
           // ss.resize(20000);
           // ss="";
           // scanf(" %s",&ss[0]);
           cin>>ss;
            string qq;
            qq=group(ss);
            str.insert(qq);

        }
       cout<<str.size()<<endl;

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值