#老师说可以尝试一下编写这样的代码,编写出来平时分直接有95分!!!好好好,我就是想学习一下这样的代码怎么写,绝对不是为了绩点!绝对不是!(老实巴交)#
在找资料的时候找到了一个有意思的网页,好像就是我想要的:圆周率查询-生日数字在圆周率中排列第几位 - 在线工具 (wqtool.com)
可惜这个网页没有代码。那我们就来搓一搓这个代码。
可不可以直接在一个程序中先把圆周率找出来储存一下,再通过字符串筛查的方法直接搜索呢?
分析一下。
1,且不说先把圆周率找出来要算多久,光是小数点后几千万位的数字的储存就挺吓人的。(也许用字符串数组可以储存)
2,且假设小数点后几千万卫的数字可以储存,那用什么方法搜索呢?目前我已知最快的字符串搜索算法--KMP.。那么已知,KMP算法的时间复杂度为O(m+n),且估算为线性时间复杂度,那么假设圆周率后有e8位。emmmm这么一算好像KMP可以实现。
3,程序中的圆周率计算。(难点)编程计算Pi(π)的N种方法_使用级数求pi的值的程序-CSDN博客https://blog.csdn.net/s170262941/article/details/11123945?spm=1001.2014.3001.5506(参考别人写的珍贵资料)
转变思路?!
把圆周率存在另一个文件中,可以直接从这个文件中KMP一下,这样就不用再算圆周率了。这样可以直接得到答案,嗯感觉要好很多。
那么去哪里弄圆周率文件呢?或许我们可以去网上直接copy一下......
当然也有其他办法--y-cruncher--一个生成pi的工具。----CPU测试相关工具搜集_y-cruncher下载-CSDN博客https://blog.csdn.net/zyhse/article/details/113242153
y-cruncher - A Multi-Threaded Pi Program (numberworld.org)http://numberworld.org/y-cruncher/
(这个文章里也有代码)
之后就是KMP了(原创)详解KMP算法 - 孤~影 - 博客园 (cnblogs.com)https://www.cnblogs.com/yjiyjige/p/3263858.html
ok工具齐全,敲代码!
圆周率查找字符串1.0
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void get_next(string T, int next[])
{
int i=0,j=-1;
next[0]=-1;
while (i<T.length())
{
if(j==-1||T[i]==T[j])
{
++i;
++j;
next[i]=j;
}
else j=next[j];
}
}
int Index_KMP(string S,string T,int pos)
{
int i = pos, j = -1;
int next[T.length()+1];
get_next(T,next);
while(i<(int)S.length() && j<(int)T.length())
{
if(j==-1||S[i]==T[j])
{
++i;
++j;
}
else j=next[j];
}
if(j==(int)T.length()) return i-T.length();
else return 0;
}
int main()
{
string data,b;
cout<<"输入你要寻找的字串:";
cin>>b;
ifstream infile;
infile.open("Pi-file.txt");
infile >> data;
cout<<"在Pi小数点后"<<Index_KMP(data,b,-1)-1<<"位";
infile.close();
return 0;
}
直接用KMP的代码去查找就好了。
效果展示
这里我的“Pi-file.txt"里存储了圆周率后十亿位。大概能查找到九位数的字符串。
然后再1.0版本的基础上做了一些更改。
写了一个能查找到字符串出现第二次与第一次相差位次的版本。
圆周率查找字符串2.0
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
long long fir=0,sec=0;
void get_next(string T, long long next[])
{
int i=0,j=-1;
next[0]=-1;
while (i<T.length())
{
if(j==-1||T[i]==T[j])
{
++i;
++j;
next[i]=j;
}
else j=next[j];
}
}
int Index_KMP(string S,string T,long long pos)
{
long long i = pos;
long long j = -1;
long long next[T.length()+1];
get_next(T,next);
while(i<(int)S.length() && j<(int)T.length())
{
if(j==-1||S[i]==T[j])
{
++i;
++j;
}
else j=next[j];
}
if(i>=(int)S.length())
return 0;
fir=i-T.length();
j=-1;
while(i<(int)S.length() && j<(int)T.length())
{
if(j==-1||S[i]==T[j])
{
++i;
++j;
}
else j=next[j];
}
if(i>=(int)S.length())
return 0;
sec=i-T.length();
if(j==(int)T.length()) return 0;
else return 0;
}
int main()
{
string data,b;
cout<<"输入你要寻找的字串:";
cin>>b;
ifstream infile;
infile.open("Pi-file.txt");
infile >> data;
Index_KMP(data,b,-1);
if(fir) {
cout<<"第一次出现在Pi小数点后"<<fir-1<<"位"<<endl;
if(sec){
cout<<"第二次出现在Pi小数点后"<<sec-1<<"位"<<endl;
cout<<"第二次与第一次相差"<<sec-fir<<"位"<<endl;
}
else{
cout<<"在十亿位次内没有找到该字符串"<<endl;
}
}
else
cout<<"在十亿位次内没有找到该字符串"<<endl;
infile.close();
return 0;
}
效果展示
当然了不仅可以找到所在位置,也可以将这一部分的字符串展示出来,加一个小小的输出就好了。
再加个循环,加个停顿,加个颜色展示。OK!
圆周率查找字符串3.0
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
#define RED "\033[0;32;31m"
#define WHITE "\033[1;37m"
long long fir=0,sec=0;
void get_next(string T, long long next[])
{
int i=0,j=-1;
next[0]=-1;
while (i<T.length())
{
if(j==-1||T[i]==T[j])
{
++i;
++j;
next[i]=j;
}
else j=next[j];
}
}
int Index_KMP(string S,string T,long long pos)
{
long long i = pos;
long long j = -1;
long long next[T.length()+1];
get_next(T,next);
while(i<(int)S.length() && j<(int)T.length())
{
if(j==-1||S[i]==T[j])
{
++i;
++j;
}
else j=next[j];
}
if(i>=(int)S.length())
return 0;
fir=i-T.length();
j=-1;
while(i<(int)S.length() && j<(int)T.length())
{
if(j==-1||S[i]==T[j])
{
++i;
++j;
}
else j=next[j];
}
if(i>=(int)S.length())
return 0;
sec=i-T.length();
if(j==(int)T.length()) return 0;
else return 0;
}
int main()
{
while(1)
{
fir=0,sec=0;
string data,b;
cout<<"输入你要寻找的字串:";
cin>>b;
ifstream infile;
infile.open("Pi-file.txt");
infile >> data;
Index_KMP(data,b,-1);
if(fir) {
cout<<"第一次出现在Pi小数点后"<<fir-1<<"位"<<endl;
cout<<"字符串展示: ";
for(long long ss=fir-10;ss<=fir+10+b.length() ;ss++)
{
if(ss>=fir&&ss<fir+b.length() )
{
cout<<RED;
cout<<data[ss];
continue;
}
cout<<WHITE;
cout<<data[ss];
}
cout<<endl;
if(sec){
cout<<"第二次出现在Pi小数点后"<<sec-1<<"位"<<endl;
cout<<"字符串展示: ";
for(long long ss=sec-10;ss<=sec+10+b.length() ;ss++)
{
if(ss>=sec&&ss<sec+b.length() )
{
cout<<RED;
cout<<data[ss];
continue;
}
cout<<WHITE;
cout<<data[ss];
}
cout<<endl;
cout<<"第二次与第一次相差"<<sec-fir<<"位"<<endl;
}
else{
cout<<"在十亿位次内没有找到该字符串"<<endl;
}
}
else
cout<<"在十亿位次内没有找到该字符串"<<endl;
infile.close();
system("Pause");
}
}
效果展示
完美!
再思考一下......
因为我的“Pi-file.txt"储存了圆周率后十亿位数字,占了1GB的内存,所以整个程序运行下来会很慢。当然也因为我的文件里只有十亿位小数,我们用来查找13位的学号可能会查找不出来。如果想要查找更长的字符串,那我们的文件的储存也要足够。比如文件里存储一百亿位数字?一千亿?。
参考文献: