zjnuSAVEZ (字符串hash)

本文介绍了一种使用字符串哈希的方法来解决一个特定问题:在一组字符串中找到最长的不下降子序列,使得序列中的每个字符串既是其后一个字符串的开头也是结尾。通过巧妙地运用哈希技巧和数据结构优化,该文提供了一个高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description


There are eight planets and one planetoid in the Solar system. It is not a well known fact that there is a secret planet S4 inhabited by small creatures similar to bears, their codename being Lodas. Although this fact is well hidden from the public, the association Savez sent a team lead by general Henrik to study the Lodas. It has been discovered that Lodas have the ability of teleportation and he wants to hire them in his army. One Lod consists of N strings where the ith string is denoted by xi . Research has shown that the number of teleportations a Loda can make depends on one special subsequence (not necessarily consecutive) of these strings. Strings xi and xj (i < j) can both be in that sequence if and only if string xj both starts with and ends with string xi . The number of teleportations a Loda can make is the length of the longest described subsequence. Determine the number of teleportations.


Input


The first line of input contains of the integer N, the number of strings. Each of the following N lines contains one string consisting of uppercase letters of the English alphabet. The input data will be such that there will be less than two million characters in total.


Output


The first and only line of output must contain the number of teleportations a Loda can make.


Sample Input




5
A
B
AA
BBB
AAA
5
A
ABA
BBB
ABABA
AAAAAB
6
A
B
A
B
A
B
Sample Output






3

题意:给你几个字符串,让你找到最长不下降子序列,使得前一个字符串是后一个字符串的开头和结尾。

思路:用字符串hash做。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define MOD 1000000007
#define maxn 2000050
#define mod1 31
#define mod2 1000000007
ll md[maxn];
map<ll,int>mp;
map<ll,int>::iterator it;


void init()
{
    int i;
    md[0]=1;
    for(i=1;i<=2000000;i++){
        md[i]=(md[i-1]*mod1)%mod2;
    }
}
char s[2000060];




int main()
{
    int n,m,i,j,len;
    init();
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0){
            printf("0\n");continue;
        }
        mp.clear();
        int ans=1;
        for(i=1;i<=n;i++){
            scanf("%s",s);
            len=strlen(s);
            int now=0;
            ll num1=0,num2=0;
            for(j=0;j<len;j++){
                num1=(num1+md[j]*(s[j]-'A'+1) )%mod2;
                num2=(num2*mod1+(s[len-1-j]-'A'+1))%mod2; //这里是关键

                if(num1==num2){
                    now=max(now,mp[num1]);
                }
            }
            ll num=0;
            for(j=0;j<len;j++){
                num=(num+(s[j]-'A'+1)*md[j])%mod2;
            }
            mp[num]=max(mp[num],now+1);
            ans=max(ans,now+1);

        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值