@SovietPower
2021-09-14T21:12:04.000000Z
字数 10488
阅读 1329
ECNU
谷歌学术:https://scholar.google.com.hk/
sci-hub:https://sci-hub.shop/
两者综合:https://gfsoso.99lb.net/
作业二选一,6月13前交:
1. 对一个具体问题设计一个算法
2. 对某类具体算法写一个综述报告
描述性的证明,非数学证明。
void GetFail(char *s)//pattern
{
int m=strlen(s+1);
for(int i=2,j=0; i<=m; ++i)
{
while(j && s[i]!=s[j+1]) j=fail[j];
fail[i]=s[i]==s[j+1]?++j:0;
}
}
void Match(char *p,char *s)
{
int j=0,n=strlen(s+1),m=strlen(p+1);
for(int i=1; i<=n; ++i)
{
while(j && s[i]!=p[j+1]) j=fail[j];
if(s[i]==p[j+1]) ++j;
if(j==m) printf("%d\n",i-m+1);
}
}
首先说明一些定义:为文本串,为模式串,表示构成的子串。
字符串的定义为:。
定义中最长子串的长度,即最长的前缀等于后缀的子串长度,为:或。
GetFail
的证明GetFail
函数用来求的。
总上,该函数正确。
Match
的证明Match
函数利用的,判断在中出现的位置。
设为当前已匹配的的前缀长度。
综上,该函数正确。
由上证明可知,两函数的计算过程本质是一样的。所以只对GetFail
函数进行证明。
记势函数。
对于算法的两种操作:
1. ,使增加。
2. ,该操作会使减少()。
因为操作1有个,所以势函数的总变化量为,所以操作2的总次数也为,均摊复杂度。
所以算法总复杂度为或。
KMP算法不只能用于字符串字符的匹配,还能用于数列中数的相对大小关系的匹配,即将相等关系,替换为,在串中的排名 等于 在串中的排名。如这道题。
这个想法感觉很妙,不知道在实际生活中,是否有这种相对大小关系的匹配需求,以及KMP的此类应用?
看完这些论文的感觉:Google提出了PageRank,之后十几年 一人改一点,就能一人写一篇论文(雾)。
你一改 我一改 大家明天都能毕业
但WPR(VOL)和EWPR(VOL)真的毫无创新性,上一个算法提出后隔年就发出来了,感觉好水。
说是综述报告,其实就是为了作业随便写的,随便看看就好。
关于PageRank的研究成果有很多,但与无权图相比带权图的算法仍然较少。
因为个人目前水平和时间问题,只对PageRank及Weighted PageRank优化方向的几个简单算法进行介绍。
L. Page, S. Brin等1于1998年提出简化的PageRank算法:
其中:表示某个网页,分别为网页的排序值(网页的排名得分,即rank score),为连向的网页集合,为的出度,为factor used for normalization(标准化参数?)。
所有网页的排序值可以通过迭代若干次计算。
但是,当一个网络中存在两个点及以上的环,且该环没有出边时,这个环会积累其它网页的排序值而不会传递出去,使得所有连向该环的网页的排序值变为,不合实际。这个问题叫做rank sink。
为解决rank sink,L. Page, S. Brin等1根据随机游走将简化的PageRank改为:
其中:为dampening factor(不跳出概率?),通常设为。
相比Simplified PageRank,该算法考虑了用户在浏览网页时有概率跳出当前浏览的网页,而任意再选择其它网页的情况,从而避免了rank sink。
作者测试了该算法,大概在次迭代后排序值会收敛。
PageRank算法的每次迭代,将每个网页的排序值平均分给了它指向的网页。但在实际中,同一网页指向的不同链接的重要性可能不同,分到的排序值也应不同。
Wenpu Xing, Ali Ghorbani2在2004年发表Weighted PageRank Algorithm,提出了Weighted PageRank(WPR)算法:
表示:考虑的入度和连向的所有点的入度,这条边该分配的多少权值:
其中:表示的入度,表示连向点的集合。
表示:考虑的出度和连向的所有点的出度,这条边该分配的多少权值:
其中:表示的出度,表示连向点的集合。
作者认为,一个网页越受欢迎,连向它的网页和它连出的网页越多。所以WPR根据指向网页集合中点的出度和入度,分配的排序值。这样排序值会更多地分配到更受欢迎的网页上,而不是均分。
作者实验表明:将WPR用于搜索,得到的结果的相关性高于传统PageRank算法。
Gyanendra Kumar等3在2011年发表Page Ranking Based on Number of Visits of Web Pages,提出了Page Ranking based on Visits of Links(VOL)算法:
其中表示用户通过链接访问的次数,表示,即用户通过上的链接访问其它网页的总次数。
该算法考虑了用户的浏览倾向,根据用户的实际浏览行为(链接的访问数)决定哪个网页更受欢迎,将更多的排序值分配到用户浏览最多(更受欢迎)的网页上。
VOL与之前算法相比具有如下特点:
1. 具有动态性,更符合网页搜索的特性。
2. 结果不是仅与网络结构相关,还与用户行为有关,更具目标导向性;而之前算法中,网页的排序值与用户实际访问该网页的情况无关。
3. 用户可以在搜索的同时提高该算法的准确性。
4. 一大问题是,需要动态统计每个网页上用户的浏览行为。
综上,VOL比传统PageRank的搜索结果更相关,但也带来了具体实现的问题。
Neelam Tyagi, Simple Sharma4在2012年发表Weighted Page Rank Algorithm Based on Number of Visits of Links of Web Page,提出了Weighted PageRank based on Visits of Links(WPR(VOL))算法:
其中:是WPR(VOL)算法计算出的的重要性,是WPR中,考虑的入度和连向的所有点的入度,这条边该分配的多少权值:
因为VOL算法中考虑了出度影响的受欢迎程度(即),作者没有使用。
该算法将WPR(网页的受欢迎程度)与VOL(用户的实际浏览行为/链接的访问数)结合,按照另一种比例分配排序值。
WPR(VOL)的特点、问题与VOL基本相同,但搜索结果相关性更强。
但是作者在论文所给例子的计算过程中,与搞混了,结果都是错的,这也能发论文吗。(下面EWPR(VOL)中这里没有错)
该算法实际只是毫无技术水平的两算法结合。
Sonal Tuteja5在2013年发表Enhancement in Weighted PageRank Algorithm Using VOL,对WPR(VOL)算法进行了优化:
改进的原因是,作者认为WPR(VOL)算法中没有考虑(事实上考虑过这点),需要加上,于是就乘了个然后发了篇新论文。
但是,论文中表述有问题,公式中的是指WPR(VOL)还是EWPR(VOL)中的网页排序值?
如果是前者,那代入后完整公式应为:
为什么就要算两次?作者没有说明为什么不同。
如果是后者,那EWPR(VOL)与WPR算法不一样吗?
下面有作者给出的例子,例子与介绍VOL算法中的例子相同,包含visit of links。但是,给出的计算过程中没有出现形如的对visits的考虑。所以上面问题答案是后者,那例子中的EWPR(VOL)就是WPR(迷惑起来了)。
然后作者给出了WPR与EWPR(VOL)在取不同值时的不同结果,这个不同结果是如何得出来的?所以个人认为是作者的例子计算过程写错了,公式也有问题。
公式应为:
该算法实际又是毫无技术水平的两算法结合+无意义的改进。
可能是我水平低吧,我认为这篇论文/这算法和CtrlCV没区别,还有问题,这期刊随便发吗。
彭茂、张媛6在2016年发表《带权网络的个性化PageRank计算_彭茂》,提出了基于操作的PageRank计算方法,其时间复杂度优于传统迭代算法。
记为PageRank中各点排序值构成的向量,为计算后的向量,为状态转移矩阵,为跳出概率。则可知为如下方程的唯一解:
传统迭代算法可表示为:
算法的误差限通常定义为:,时间复杂度为。
作者给出了带权图的一个近似PageRank计算方法,复杂度上界为,其中为图顶点的最大出度。算法如下。
若为非负向量,且对任意顶点有,则称向量为PageRank向量的近似。
该算法持续更新一个向量对,使其始终满足:
即
算法初始时,通过如下操作更新(记为操作后所得向量):
对某个点:
1.
2.
3. (对所有满足的)
未更新的。
若为转移矩阵,则;为预设值,默认为。
可知。
因为过程可以看做,中的某些概率转移到了中,所以对所有满足的点执行操作,可得到如下计算近似PageRank向量方法:
ApxPR(s, α, ε)
Let p=0 and r=s
while r(u)>ε*outdgree(u) for some vertex u
Pick any vertex u where r(u)>ε*outdgree(u)
Apply Push(u)
return p and r
作者证明了该APXPR算法时间复杂度为,其中为图顶点的最大出度,远优于迭代算法的。
该算法也支持动态带权网络修改,更新网络一条边的复杂度为,且实际计算时间会小很多。而传统幂迭代法只能重新计算。动态网络的计算这里不再展开。
此外,作者介绍了蒙特卡洛策略计算PageRank向量的方法,也支持在线更新网络。对于一个个顶点、条边的图,保持条边持续更新的复杂度为。
作者通过实验得出:
1. 静态图中算法与蒙特卡洛算法均优于幂迭代法;图的稠密度较高时蒙特卡洛算法优于算法。
2. 动态图中,在图的更新量较少时,算法优于蒙特卡洛方法。
对WPR(VOL)算法与ApxPR算法的简单实现(节点数较小时)。
在节点数、边数不大时,算法实现很简单,但当节点数很大,即现实中网页数非常多时,可能需要改进实现方法。
每次迭代复杂度为。
/*
Sample Input:
3 4
1 3 2
3 1 2
1 2 1
2 3 2
Output:
WPR[1]=0.6319057
WPR[2]=0.2096800
WPR[3]=0.5669479
*/
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
#define pb emplace_back
typedef long long LL;
const int N=1e3+5;
const double d=0.85;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
struct Edge
{
int v,w;
};
struct Graph
{
std::vector<int> e[N];
};
struct PageRank
{
Graph R,B;
int n,L[N][N],TL[N],I[N],O[N];
double WPR[N],W_in[N][N],W_out[N][N];
void AddEdge(int w,int v,int u)
{
R.e[u].pb(v), B.e[v].pb(u);
++I[v], ++O[u], L[u][v]+=w, TL[u]+=w;
}
void Output()
{
for(int i=1; i<=n; ++i) printf("WPR[%d]=%.7f\n",i,WPR[i]);
}
void WPRVOL()
{
for(int u=1; u<=n; ++u)
{
double sum=0;
for(auto v:B.e[u]) sum+=L[v][u]*WPR[v]*W_in[v][u]/TL[v];
WPR[u]=1-d+d*sum;
}
}
void Calc()
{
//Init WPR
for(int i=1; i<=n; ++i) WPR[i]=1;
//Calc W_in W_out
for(int u=1; u<=n; ++u)
{
if(!R.e[u].size()) continue;
int sumI=0,sumO=0;
for(auto v:R/*B*/.e[u]) sumI+=I[v], sumO+=O[v];//这里WPR(VOL)论文中使用的B(u)
for(auto v:R.e[u]) W_in[u][v]=1.0*I[v]/sumI, W_out[u][v]=1.0*O[v]/sumO;
}
//Calc values iteratively
for(int T=300,t=1; t<=T; ++t)//应该有一个校验误差是否满足的函数,不写了
{
WPRVOL();
// printf("\nIteration %d:\n",t), Output();
}
Output();
}
void Init()
{
n=read();
for(int m=read(); m--; AddEdge(read(),read(),read()));
Calc();
}
}PR;
int main()
{
PR.Init();
return 0;
}
/*
Sample Input:
3 4
1 3 2
3 1 2
1 2 1
2 3 2
Output:
PR[1]=1.2303706
PR[2]=0.4986050
PR[3]=1.2710243
*/
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
#define pb emplace_back
typedef long long LL;
const int N=1e3+5;
const double d=0.85;
const double alpha=1-d, beta=0.5, epsilon=1e-8;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
struct Edge
{
int v,w;
};
struct Graph
{
std::vector<int> e[N];
};
struct PageRank
{
Graph R,B;
int n,I[N],O[N],A[N][N];
double p[N],r[N],w[N][N];
void AddEdge(int w,int v,int u)
{
R.e[u].pb(v), B.e[v].pb(u);
++I[v], ++O[u], A[u][v]+=w;
}
void Output()
{
for(int i=1; i<=n; ++i) printf("PR[%d]=%.7f\n",i,p[i]);
}
int Exist(double e)
{
for(int u=1; u<=n; ++u)
if(r[u]>e*O[u]) return u;
return 0;
}
void Push(int u,double a,double b)
{
p[u]=p[u]+a*b*r[u];
for(auto v:R.e[u]) r[v]=r[v]+(1-a)*w[u][v]*b*r[u];
r[u]=r[u]-b*r[u]+(1-a)*0*b*r[u];
}
void ApxPR(double a,double e,double b)
{
//Init
for(int i=1; i<=n; ++i) p[i]=0, r[i]=1;
//APXPR
int u;
while(u=Exist(e),u) Push(u,a,b);
}
void Init()
{
n=read();
for(int m=read(); m--; AddEdge(read(),read(),read()));
//Calc wij
for(int i=1; i<=n; ++i)
{
int D=0;
for(int j=1; j<=n; ++j) D+=A[i][j];
for(int j=1; j<=n; ++j) w[i][j]=1.0*A[i][j]/D;
}
//ApxPR
ApxPR(alpha,epsilon,beta);
Output();
}
}PR;
int main()
{
PR.Init();
return 0;
}
PageRank最初的几个算法虽然容易理解,但在当时确实很具有创新性,比如PageRank、Weighted PageRank和PageRank based on Visits of Links。
但是之后的提出的两个算法 WPR(VOL)和EWPR(VOL),只是简单地将前面的算法进行结合,没太有创新性,且内容都有很大的错误,合理怀疑只是在水论文。
除了幂迭代法,还有很多其它算法,也比迭代法更复杂、有创意。