似乎大家全部都用的是hash?那我讲一个不用hash的做法吧。

首先考虑只有一位不同的是哪一位,那么这一位前面的位上的字符一定是全部相同,后面的字符也是全部相同。首先考虑后面的字符。

我们对n个串的反串建trie树,这样,每一个后缀就对应一个trie树上的唯一一个节点,不同的后缀对应的就是不同的节点,这样就不用hash表了。

但是字符集很大,用trie空间太大,那么就用邻接表或map存边就好了。

然后就是令前缀全部相同。那么我们从左到右枚举每一位,按照当前位的字符进行分治,当前位不同的就通过后缀计算贡献,相同的就放在一起,继续分治即可。

然后就跑的飞快,目前是BZOJ rk2,Luogu rk1。

实现的时候有很多细节,具体请参考代码。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#define qmin(x,y) (x=min(x,y))
#define qmax(x,y) (x=max(x,y))
#define vi vector<int>
#define vit vector<int>::iterator
#define pir pair<int,int>
#define fr first
#define sc second
#define mp(x,y) make_pair(x,y)
#define rsort(x,y) sort(x,y),reverse(x,y)
using namespace std; inline char gc() {
// static char buf[100000],*p1,*p2;
// return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
return getchar();
} template<class T>
int read(T &ans) {
ans=0;char ch=gc();T f=1;
while(!isdigit(ch)) {
if(ch==EOF) return -1;
if(ch=='-') f=-1;
ch=gc();
}
while(isdigit(ch))
ans=ans*10+ch-'0',ch=gc();
ans*=f;return 1;
} template<class T1,class T2>
int read(T1 &a,T2 &b) {
return read(a)!=EOF&&read(b)!=EOF?2:EOF;
} template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
return read(a,b)!=EOF&&read(c)!=EOF?3:EOF;
} typedef long long ll;
const int Maxn=6100000;
const int Maxm=31000;
const int Maxl=210;
const int inf=0x3f3f3f3f; int to[Maxn],nxt[Maxn],first[Maxn],tot=1;
char w[Maxn],s[Maxm][Maxl];
int p[Maxm][Maxl],n,len,x,po[Maxl][Maxl],qq[Maxl],bj[Maxl],ans;
int a[Maxm],siz[Maxl],b[Maxm],tn[Maxn],cnt=1;
queue<int> q[Maxl]; inline void add(int u,int v,char wi) {
to[tot]=v;
nxt[tot]=first[u];
w[tot]=wi;
first[u]=tot++;
} void solve(int l,int r,int cur) {
if(l>r) return ;
if(cur==len) return ;
int cnt=0;
for(int i=l;i<=r;i++) {
int x=s[a[i]][cur];
q[x].push(a[i]);
siz[x]++;
if(!bj[x]) qq[++cnt]=x,bj[x]=1;
}
if(cnt==1) {
for(int i=1;i<=cnt;i++) bj[qq[i]]=siz[qq[i]]=0;
while(!q[qq[1]].empty()) q[qq[1]].pop();
solve(l,r,cur+1);
}
else {
int sxz,zhy=0;
for(int i=1;i<=cnt;i++) {
if(siz[qq[i]]>zhy) {
sxz=i;
zhy=siz[qq[i]];
}
}
swap(qq[cnt],qq[sxz]);
int las=l;po[cur][0]=las;
for(int i=1;i<cnt;i++) {
int x=qq[i],num=0;
while(!q[x].empty()) {
int now=q[x].front();
q[x].pop();
b[++num]=p[now][cur+1];
ans+=tn[b[num]];
a[las++]=now;
}
while(num) tn[b[num--]]++;
po[cur][i]=las;
}
while(!q[qq[cnt]].empty()) {
int now=q[qq[cnt]].front();
q[qq[cnt]].pop();
ans+=tn[p[now][cur+1]];
a[las++]=now;
} po[cur][cnt]=las;
for(int i=l;i<po[cur][cnt-1];i++) tn[p[a[i]][cur+1]]--;
for(int i=1;i<=cnt;i++) bj[qq[i]]=siz[qq[i]]=0;
for(int i=1;i<=cnt;i++)
solve(po[cur][i-1],po[cur][i]-1,cur+1);
}
} signed main() {
// freopen("test.in","r",stdin);
read(n,len,x);
for(int i=1;i<=n;i++) {
scanf("%s",s[i]);
int now=1;
for(int j=len-1;j>=0;j--) {
int temp=0;
for(int k=first[now];k;k=nxt[k])
if(w[k]==s[i][j]) {
temp=to[k];
break;
}
if(!temp) add(now,++cnt,s[i][j]),temp=cnt;
now=temp;
p[i][j]=now;
}
}
for(int i=1;i<=n;i++) a[i]=i;
solve(1,n,0);
printf("%d\n",ans);
return 0;
}

BZOJ 3555: [Ctsc2014]企鹅QQ的更多相关文章

  1. BZOJ 3555: [Ctsc2014]企鹅QQ [字符串哈希]【学习笔记】

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 2046  Solved: 749[Submit][Statu ...

  2. BZOJ 3555: [Ctsc2014]企鹅QQ hash

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  3. bzoj——3555: [Ctsc2014]企鹅QQ

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 2617  Solved: 921[Submit][Statu ...

  4. 字符串Hash || BZOJ 3555: [Ctsc2014]企鹅QQ || P4503 [CTSC2014]企鹅QQ

    题面:[CTSC2014]企鹅QQ 题解:无 代码: #include<iostream> #include<cstring> #include<cstdio> # ...

  5. bzoj 3555: [Ctsc2014]企鹅QQ【hash+瞎搞】

    首先注意 先hash一下,双hash,然后枚举删去位置,把hash值排个序,把些相等的加起来统计一下对数即可 #include<iostream> #include<cstdio&g ...

  6. 3555: [Ctsc2014]企鹅QQ

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 696  Solved: 294[Submit][Status ...

  7. bzoj3555: [Ctsc2014]企鹅QQ

    将字符串hash.不难写.然而1.注意用longlong2.数组大小注意...3.似乎别人都用的unsigned long long ?. #include<cstdio> #includ ...

  8. [Ctsc2014]企鹅QQ

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description P ...

  9. 【BZOJ3555】 [Ctsc2014]企鹅QQ

    BZOJ3555 [Ctsc2014]企鹅QQ Solution 只需要前缀Hash,然后考虑每一段的贡献就好了!!! 代码实现 #include<stdio.h> #include< ...

随机推荐

  1. Netty In Action中文版 - 第三章:Netty核心概念

            在这一章我们将讨论Netty的10个核心类.清楚了解他们的结构对使用Netty非常实用.可能有一些不会再工作中用到.可是也有一些非经常常使用也非常核心,你会遇到. Bootstrap ...

  2. 002-redis-数据类型

    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 使用桌面工具查看,默认有16个库,Redis支持多 ...

  3. 【剑指offer】用两个栈实现队列

    一.题目: 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 二.思路: 两个栈A,B,A负责进栈,B负责出栈,进栈很容易,A中添加即可,出栈需要从B里出,所以要先 ...

  4. java读取resource目录下的配置文件

    java读取resource目录下的配置文件 1:配置resource目录 下的文件 host: 127.0.0.1 port: 9300 2:读取    / 代表resource目录 InputSt ...

  5. 详解Linux(centos7)下安装OpenSSL安装图文方法

    OpenSSL是一个开源的ssl技术,由于我需要使用php相关功能,需要获取https的文件所以必须安装这个东西了,下面我整理了两种关于OpenSSL安装配置方法. 安装环境:  操作系统:CentO ...

  6. Selenium - Css Selector 使用方法

    什么是Css Selector? Css Selector定位实际就是HTML的Css选择器的标签定位 工具 Css Selector可以下载火狐浏览器插件,FireFinder 或 FireBug和 ...

  7. JDK eclipse selenium 安装以及环境变量的配置

    原文地址https://www.cnblogs.com/zmhsoup/p/5249663.html [自动化学习笔记]_环境搭建Selenium2+Eclipse+Java+TestNG_(一) 目 ...

  8. mui笔记

    1.关闭当前页面执行上一个页面的方法 var preview = plus.webview.currentWebview().opener() //获取当前窗口的创建者,即A preview.eval ...

  9. C语言标准函数源代码

    http://ftp.gnu.org/gnu/glibc/ 最新glibc-2.27.tar.gz 直接解压就可以

  10. liferay中如何获取实例的id和portletId

    在Portlet中request分为两种renderRequet和actionRequest而portlet需要取得实例Id的时候都在renderRequest的时候才可以取到,如下例子 Portle ...