博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字符串 专题
阅读量:4313 次
发布时间:2019-06-06

本文共 3034 字,大约阅读时间需要 10 分钟。

 

今天复习字符巛 还剩下一点时间  我先 打一下模板

$ 1$  最小表示法

贪心 首先把 $ S $ 复制一遍成一个环 

然后定义两个指针  i j 从 i j 开始一次扩展 字符巛 的长度  即  从$0$ 的长度开始扩展到 $n-1$  ($k $最大到 $n$ >- 停止循环 找到答案)

然后比较其中是否相等  

如果不相等就跳过循环 

判断 当前 $S[i+k]$ 与$S[j+k]$ 的 大小 因为中间的字符串 都相等 所以 指针可以跳到  $x+k+1$ 处 $[x|i,j]$ 

然后因为 最小的指针一定不会移动到最大的指针的后面所以 答案为 $min(i,j)$

$ i,j $只循环到 n 的位置 因为以后都是一样的 了 

 

code;

int i=1,j=2;int k=0;while(i<=n&&j<=n){        for(int k=0;k
s[j+k]) i=i+k+1; else    {      if(s[i+k]

 

 

2 .01 字典树

 作用 : 寻找异或最大值 

方法 :

 

   插入: 每位每位地找 没有就扩展 扩展完之后 就插入

code:

void inset(int v){    int u=0;    for(int i=32;i>=0;i--)    {        int k=(sum[v]>>i)&1;        if(!ch[u][k])        {            ch[u][k]=tot++;        }        u=ch[u][k];    }    val[u]=sum[v];}

 

 寻找:从最高位 开始 搜寻 先找 不同的 后找相同的 注意 先插入 $sum[0]$ 保证有解 

      如果 找不到 就一定没有

code:

int find(int v){    int u=0;    for(int i=32;i>=0;i--)    {        int k=(v>>i)&1;        if(ch[u][k^1]) u=ch[u][k^1];        else        u=ch[u][k];    }    return val[u];}

 

 

$3$ 状态很差,但是还是坚持来写下博客啦

KMP

作用 匹配或者最长字串

首先 fail数组 记的是 前i位 的最长前缀和后缀 

求fail 数组首先得与自己比对  注意得从第二位开始 求出回退值

code:

fail[0]=-1;        int j=-1;        for(int i=1;i
-1&&(s[1][j+1]!=s[1][i])) j=fail[j]; if(s[1][j+1]==s[1][i]) j++; fail[i]=j; }

求匹配   匹配使得前后缀一样 就很强 从第一位开始

int j=-1;    int ans=0;    fail[0]=-1;    for(int i=0;i
-1&&(s[1][j+1]!=s[v][i])) { ans=max(ans,j); j=fail[j];} if(s[1][j+1]==s[v][i]) j++;     if(j==m)      {
     
        ans=max(j+1,ans);      }     }    return ans;

$@$求最长公共字串匹配

找一个串 然后挨个匹配 找最小值 然后删除第一个元素 再次找最小值 最后取max 

介绍一下动态数组的erase神操作

 

#include
using namespace std;int n;string s[8];int fail[3000];int kmp(int v){ int j=-1; int ans=0; fail[0]=-1; for(int i=0;i
-1&&(s[1][j+1]!=s[v][i])) { ans=max(ans,j); j=fail[j];} if(s[1][j+1]==s[v][i]) j++; ans=max(ans,j+1); } return ans;}int main(){ cin>>n; for(int i=1;i<=n;i++) { cin>>s[i]; } int aans=0; while(s[1].size()) { int ans=100000000; fail[0]=-1; int j=-1; for(int i=1;i
-1&&(s[1][j+1]!=s[1][i])) j=fail[j]; if(s[1][j+1]==s[1][i]) j++; fail[i]=j; } for(int i=2;i<=n;i++) { ans=min(ans,kmp(i)); } aans=max(aans,ans); s[1].erase(s[1].begin()); } cout<

  

 

$@@$结论 字符串乘方 i%(i-fail[i])==0 那么一定有乘方 个数为$i/(i-fail[i])$

 $4$马拉车

首先初始化 把回文串都变成奇数回文串

类似于这样

void init(){    S[0]='#';    S[1]='#';    for(int i=0;i

 

一共由两种大情况 i 在已经更新的回文串maxlen 的右边或左边

对于i在左边的情况 $r[i] =min|{r[2*p-i],maxlen-i+1}|$ 其中$2*p-i$是$i$ 关于$p $对称的回文对应位置

对于i 在右边的情况 $r[i]=1$ 

     if(i

 

然后挨着扩展

类似于这样

while(S[i-r[i]]==S[i+r[i]])r[i]++;

最后更新maxlen 和p 的$val$

    if(i+r[i]-1>maxlen)         {             maxlen=i+r[i]-1;             P=i;         }

 

注意到r数组位是最长回文半径(包括自己)

$r[i]-1$ 是原字符串的回文长度

         

string 类型可以直接比较  字典序

strcpy strcmp strlen 字符数组的函数

转载于:https://www.cnblogs.com/OIEREDSION/p/11338801.html

你可能感兴趣的文章
JavaScript高级特性-实现继承的七种方式
查看>>
20121016学习笔记四
查看>>
EntityFramework 学习 一 Stored Procedure
查看>>
Sliverlight之 故事板
查看>>
Java 必知必会的 20 种常用类库和 API
查看>>
HDU 1087 Super Jumping! Jumping! Jumping!
查看>>
0007_初始模块和字节码
查看>>
[效率提升]如何管理好你的电脑文件
查看>>
C++实验二
查看>>
Sultan's Dowry Problem - 苏丹新娘问题
查看>>
SharePoint2010 富文本框添加图片功能的扩展
查看>>
零零碎碎的知识
查看>>
UNIX基础--用户和基本账户管理
查看>>
设计模式
查看>>
5.0以上机器XPOSED框架安装流程
查看>>
静态方法与非静态方法
查看>>
[转]iOS进阶路线以及进阶书籍
查看>>
期货监管机构,国际著名。
查看>>
vim编程技巧
查看>>
Activator.CreateInstance 方法 (Type) 的用法
查看>>